MediaRouteActionProvider.java revision 39d5c6172503620ac3761148adac5fd7fa20d02d
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;
29690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
3039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powellimport java.lang.ref.WeakReference;
3139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
32690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellpublic class MediaRouteActionProvider extends ActionProvider {
33690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private static final String TAG = "MediaRouteActionProvider";
34690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
35690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private Context mContext;
36690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private MediaRouter mRouter;
37690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private MenuItem mMenuItem;
38690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private MediaRouteButton mView;
39690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    private int mRouteTypes;
40b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    private View.OnClickListener mExtendedSettingsListener;
4139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell    private RouterCallback mCallback;
42690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
43690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public MediaRouteActionProvider(Context context) {
44690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        super(context);
45690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mContext = context;
46b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
4739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        mCallback = new RouterCallback(this);
48690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
49690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // Start with live audio by default.
50690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // TODO Update this when new route types are added; segment by API level
51690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        // when different route types were added.
52690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
53690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
54690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
55690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public void setRouteTypes(int types) {
5639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        if (mRouteTypes == types) return;
5739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        if (mRouteTypes != 0) {
5839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            mRouter.removeCallback(mCallback);
5939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        }
60690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mRouteTypes = types;
6139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        if (types != 0) {
6239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            mRouter.addCallback(types, mCallback);
6339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        }
64690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mView != null) {
65690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            mView.setRouteTypes(mRouteTypes);
66690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
67690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
68690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
69690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
70690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public View onCreateActionView() {
71690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        throw new UnsupportedOperationException("Use onCreateActionView(MenuItem) instead.");
72690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
73690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
74690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
75690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public View onCreateActionView(MenuItem item) {
76690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        if (mMenuItem != null || mView != null) {
77690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell            Log.e(TAG, "onCreateActionView: this ActionProvider is already associated " +
78690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    "with a menu item. Don't reuse MediaRouteActionProvider instances! " +
79690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell                    "Abandoning the old one...");
80690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        }
81690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mMenuItem = item;
82690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mView = new MediaRouteButton(mContext);
83690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        mView.setRouteTypes(mRouteTypes);
84b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        mView.setExtendedSettingsClickListener(mExtendedSettingsListener);
85690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return mView;
86690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
87690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
88690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    @Override
89690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    public boolean onPerformDefaultAction() {
9070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        final FragmentManager fm = getActivity().getFragmentManager();
9170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        // See if one is already attached to this activity.
9270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        MediaRouteChooserDialogFragment dialogFragment =
9370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                (MediaRouteChooserDialogFragment) fm.findFragmentByTag(
9470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                MediaRouteChooserDialogFragment.FRAGMENT_TAG);
9570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (dialogFragment != null) {
9670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            Log.w(TAG, "onPerformDefaultAction(): Chooser dialog already showing!");
9770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return false;
9870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
9970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
10070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        dialogFragment = new MediaRouteChooserDialogFragment();
10170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        dialogFragment.setExtendedSettingsClickListener(mExtendedSettingsListener);
10270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        dialogFragment.setRouteTypes(mRouteTypes);
10370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        dialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG);
104690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell        return true;
105690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
106690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
10770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private Activity getActivity() {
10870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        // Gross way of unwrapping the Activity so we can get the FragmentManager
10970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        Context context = mContext;
11070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        while (context instanceof ContextWrapper && !(context instanceof Activity)) {
11170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            context = ((ContextWrapper) context).getBaseContext();
11270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
11370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (!(context instanceof Activity)) {
11470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            throw new IllegalStateException("The MediaRouteActionProvider's Context " +
11570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                    "is not an Activity.");
11670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
11770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
11870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        return (Activity) context;
11970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
12070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
121b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    public void setExtendedSettingsClickListener(View.OnClickListener listener) {
122b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        mExtendedSettingsListener = listener;
123b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        if (mView != null) {
124b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell            mView.setExtendedSettingsClickListener(listener);
125b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell        }
126b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell    }
127b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell
128130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell    @Override
129130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell    public boolean overridesItemVisibility() {
130130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell        return true;
131130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell    }
132690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell
133130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell    @Override
134130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell    public boolean isVisible() {
135130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell        return mRouter.getRouteCount() > 1;
136690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell    }
13739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
13839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell    private static class RouterCallback extends MediaRouter.SimpleCallback {
13939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        private WeakReference<MediaRouteActionProvider> mAp;
14039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
14139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        RouterCallback(MediaRouteActionProvider ap) {
14239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            mAp = new WeakReference<MediaRouteActionProvider>(ap);
14339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        }
14439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
14539d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        @Override
14639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        public void onRouteAdded(MediaRouter router, RouteInfo info) {
14739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            final MediaRouteActionProvider ap = mAp.get();
14839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            if (ap == null) {
14939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell                router.removeCallback(this);
15039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell                return;
15139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            }
15239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
15339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            ap.refreshVisibility();
15439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        }
15539d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
15639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        @Override
15739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
15839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            final MediaRouteActionProvider ap = mAp.get();
15939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            if (ap == null) {
16039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell                router.removeCallback(this);
16139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell                return;
16239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            }
16339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell
16439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell            ap.refreshVisibility();
16539d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell        }
16639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell    }
167690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell}
168