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, onPrepareCallbackFlags());
95            }
96        }
97    }
98
99    private void ensureRouteSelector() {
100        if (mSelector == null) {
101            Bundle args = getArguments();
102            if (args != null) {
103                mSelector = MediaRouteSelector.fromBundle(args.getBundle(ARGUMENT_SELECTOR));
104            }
105            if (mSelector == null) {
106                mSelector = MediaRouteSelector.EMPTY;
107            }
108        }
109    }
110
111    /**
112     * Called to create the {@link android.support.v7.media.MediaRouter.Callback callback}
113     * that will be registered.
114     * <p>
115     * The default callback does nothing.  The application may override this method to
116     * supply its own callback.
117     * </p>
118     *
119     * @return The new callback, or null if no callback should be registered.
120     */
121    public MediaRouter.Callback onCreateCallback() {
122        return new MediaRouter.Callback() { };
123    }
124
125    /**
126     * Called to prepare the callback flags that will be used when the
127     * {@link android.support.v7.media.MediaRouter.Callback callback} is registered.
128     * <p>
129     * The default implementation returns {@link MediaRouter#CALLBACK_FLAG_REQUEST_DISCOVERY}.
130     * </p>
131     *
132     * @return The desired callback flags.
133     */
134    public int onPrepareCallbackFlags() {
135        return MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY;
136    }
137
138    @Override
139    public void onStart() {
140        super.onStart();
141
142        ensureRouteSelector();
143        ensureRouter();
144        mCallback = onCreateCallback();
145        if (mCallback != null) {
146            mRouter.addCallback(mSelector, mCallback, onPrepareCallbackFlags());
147        }
148    }
149
150    @Override
151    public void onStop() {
152        if (mCallback != null) {
153            mRouter.removeCallback(mCallback);
154            mCallback = null;
155        }
156
157        super.onStop();
158    }
159}
160