1/*
2 * Copyright (C) 2013 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.support.v7.app;
18
19import android.os.Bundle;
20import android.support.v4.app.Fragment;
21import android.support.v7.media.MediaRouter;
22import android.support.v7.media.MediaRouteSelector;
23
24/**
25 * Media route discovery fragment.
26 * <p>
27 * This fragment takes care of registering a callback for media route discovery
28 * during the activity's {@link android.app.Activity#onStart onStart()} phase
29 * and removing it during the {@link android.app.Activity#onStart onStop()} phase.
30 * </p><p>
31 * The application must supply a route selector to specify the kinds of routes
32 * to discover.  The application may also override {@link #onCreateCallback} to
33 * provide the {@link MediaRouter} callback to register.
34 * </p>
35 */
36public class MediaRouteDiscoveryFragment extends Fragment {
37    private final String ARGUMENT_SELECTOR = "selector";
38
39    private MediaRouter mRouter;
40    private MediaRouteSelector mSelector;
41    private MediaRouter.Callback mCallback;
42
43    public MediaRouteDiscoveryFragment() {
44    }
45
46    /**
47     * Gets the media router instance.
48     */
49    public MediaRouter getMediaRouter() {
50        ensureRouter();
51        return mRouter;
52    }
53
54    private void ensureRouter() {
55        if (mRouter == null) {
56            mRouter = MediaRouter.getInstance(getActivity());
57        }
58    }
59
60    /**
61     * Gets the media route selector for filtering the routes to be discovered.
62     *
63     * @return The selector, never null.
64     */
65    public MediaRouteSelector getRouteSelector() {
66        ensureRouteSelector();
67        return mSelector;
68    }
69
70    /**
71     * Sets the media route selector for filtering the routes to be discovered.
72     * This method must be called before the fragment is added.
73     *
74     * @param selector The selector to set.
75     */
76    public void setRouteSelector(MediaRouteSelector selector) {
77        if (selector == null) {
78            throw new IllegalArgumentException("selector must not be null");
79        }
80
81        ensureRouteSelector();
82        if (!mSelector.equals(selector)) {
83            mSelector = selector;
84
85            Bundle args = getArguments();
86            if (args == null) {
87                args = new Bundle();
88            }
89            args.putBundle(ARGUMENT_SELECTOR, selector.asBundle());
90            setArguments(args);
91
92            if (mCallback != null) {
93                mRouter.removeCallback(mCallback);
94                mRouter.addCallback(mSelector, mCallback,
95                        MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
96            }
97        }
98    }
99
100    private void ensureRouteSelector() {
101        if (mSelector == null) {
102            Bundle args = getArguments();
103            if (args != null) {
104                mSelector = MediaRouteSelector.fromBundle(args.getBundle(ARGUMENT_SELECTOR));
105            }
106            if (mSelector == null) {
107                mSelector = MediaRouteSelector.EMPTY;
108            }
109        }
110    }
111
112    /**
113     * Called to create the {@link android.support.v7.media.MediaRouter.Callback callback}
114     * that will be registered.
115     * <p>
116     * The default callback does nothing.  The application may override this method to
117     * supply its own callback.
118     * </p>
119     *
120     * @return The new callback, or null if no callback should be registered.
121     */
122    public MediaRouter.Callback onCreateCallback() {
123        return new MediaRouter.Callback() { };
124    }
125
126    /**
127     * Called to prepare the callback flags that will be used when the
128     * {@link android.support.v7.media.MediaRouter.Callback callback} is registered.
129     * <p>
130     * The default implementation returns {@link MediaRouter#CALLBACK_FLAG_REQUEST_DISCOVERY}.
131     * </p>
132     *
133     * @return The desired callback flags.
134     */
135    public int onPrepareCallbackFlags() {
136        return MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY;
137    }
138
139    @Override
140    public void onStart() {
141        super.onStart();
142
143        ensureRouteSelector();
144        ensureRouter();
145        mCallback = onCreateCallback();
146        if (mCallback != null) {
147            mRouter.addCallback(mSelector, mCallback, onPrepareCallbackFlags());
148        }
149    }
150
151    @Override
152    public void onStop() {
153        if (mCallback != null) {
154            mRouter.removeCallback(mCallback);
155            mCallback = null;
156        }
157
158        super.onStop();
159    }
160}
161