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