SampleMediaRouteProvider.java revision ecdd1b114d4fb36682cdabe205e08e6f68f79f63
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 com.example.android.supportv7.media;
18
19import com.example.android.supportv7.R;
20
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.IntentFilter.MalformedMimeTypeException;
25import android.content.res.Resources;
26import android.media.MediaRouter;
27import android.net.Uri;
28import android.os.Bundle;
29import android.support.v7.media.MediaControlIntent;
30import android.support.v7.media.MediaRouteProvider;
31import android.support.v7.media.MediaRouter.ControlRequestCallback;
32import android.util.Log;
33import android.widget.Toast;
34
35/**
36 * Demonstrates how to create a custom media route provider.
37 *
38 * @see SampleMediaRouteProviderService
39 */
40final class SampleMediaRouteProvider extends MediaRouteProvider {
41    private static final String TAG = "SampleMediaRouteProvider";
42
43    private static final String FIXED_VOLUME_ROUTE_ID = "fixed";
44    private static final String VARIABLE_VOLUME_ROUTE_ID = "variable";
45    private static final int VOLUME_MAX = 10;
46
47    /**
48     * A custom media control intent category for special requests that are
49     * supported by this provider's routes.
50     */
51    public static final String CATEGORY_SAMPLE_ROUTE =
52            "com.example.android.supportv4.media.CATEGORY_SAMPLE_ROUTE";
53
54    /**
55     * A custom media control intent action for special requests that are
56     * supported by this provider's routes.
57     * <p>
58     * This particular request is designed to return a bundle of not very
59     * interesting statistics for demonstration purposes.
60     * </p>
61     *
62     * @see #DATA_PLAYBACK_COUNT
63     */
64    public static final String ACTION_GET_STATISTICS =
65            "com.example.android.supportv4.media.ACTION_GET_STATISTICS";
66
67    /**
68     * {@link #ACTION_GET_STATISTICS} result data: Number of times the
69     * playback action was invoked.
70     */
71    public static final String DATA_PLAYBACK_COUNT =
72            "com.example.android.supportv4.media.EXTRA_PLAYBACK_COUNT";
73
74    private static final IntentFilter[] CONTROL_FILTERS;
75    static {
76        CONTROL_FILTERS = new IntentFilter[2];
77
78        CONTROL_FILTERS[0] = new IntentFilter();
79        CONTROL_FILTERS[0].addCategory(CATEGORY_SAMPLE_ROUTE);
80        CONTROL_FILTERS[0].addAction(ACTION_GET_STATISTICS);
81
82        CONTROL_FILTERS[1] = new IntentFilter();
83        CONTROL_FILTERS[1].addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
84        CONTROL_FILTERS[1].addAction(MediaControlIntent.ACTION_PLAY);
85        CONTROL_FILTERS[1].addDataScheme("http");
86        CONTROL_FILTERS[1].addDataScheme("https");
87        addDataTypeUnchecked(CONTROL_FILTERS[1], "video/*");
88    }
89
90    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
91        try {
92            filter.addDataType(type);
93        } catch (MalformedMimeTypeException ex) {
94            throw new RuntimeException(ex);
95        }
96    }
97
98    private int mVolume = 5;
99    private int mPlaybackCount;
100
101    public SampleMediaRouteProvider(Context context) {
102        super(context);
103
104        publishRoutes();
105    }
106
107    @Override
108    public RouteController onCreateRouteController(String routeId) {
109        return new SampleRouteController(routeId);
110    }
111
112    private void publishRoutes() {
113        Resources r = getContext().getResources();
114
115        RouteDescriptor routeDescriptor1 = new RouteDescriptor(
116                FIXED_VOLUME_ROUTE_ID,
117                r.getString(R.string.fixed_volume_route_name));
118        routeDescriptor1.setControlFilters(CONTROL_FILTERS);
119        routeDescriptor1.setIconResource(R.drawable.media_route_icon);
120        routeDescriptor1.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE);
121        routeDescriptor1.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED);
122        routeDescriptor1.setVolume(VOLUME_MAX);
123
124        RouteDescriptor routeDescriptor2 = new RouteDescriptor(
125                VARIABLE_VOLUME_ROUTE_ID,
126                r.getString(R.string.variable_volume_route_name));
127        routeDescriptor2.setControlFilters(CONTROL_FILTERS);
128        routeDescriptor2.setIconResource(R.drawable.media_route_icon);
129        routeDescriptor2.setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE);
130        routeDescriptor2.setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE);
131        routeDescriptor2.setVolumeMax(VOLUME_MAX);
132        routeDescriptor2.setVolume(mVolume);
133
134        ProviderDescriptor providerDescriptor = new ProviderDescriptor();
135        providerDescriptor.setRoutes(new RouteDescriptor[] {
136            routeDescriptor1, routeDescriptor2
137        });
138        setDescriptor(providerDescriptor);
139    }
140
141    private final class SampleRouteController extends MediaRouteProvider.RouteController {
142        private final String mRouteId;
143
144        public SampleRouteController(String routeId) {
145            mRouteId = routeId;
146            Log.d(TAG, mRouteId + ": Controller created");
147        }
148
149        @Override
150        public void release() {
151            Log.d(TAG, mRouteId + ": Controller released");
152        }
153
154        @Override
155        public void select() {
156            Log.d(TAG, mRouteId + ": Selected");
157        }
158
159        @Override
160        public void unselect() {
161            Log.d(TAG, mRouteId + ": Unselected");
162        }
163
164        @Override
165        public void setVolume(int volume) {
166            Log.d(TAG, mRouteId + ": Set volume to " + volume);
167            if (mRouteId.equals(VARIABLE_VOLUME_ROUTE_ID)) {
168                setVolumeInternal(volume);
169            }
170        }
171
172        @Override
173        public void updateVolume(int delta) {
174            Log.d(TAG, mRouteId + ": Update volume by " + delta);
175            if (mRouteId.equals(VARIABLE_VOLUME_ROUTE_ID)) {
176                setVolumeInternal(mVolume + delta);
177            }
178        }
179
180        private void setVolumeInternal(int volume) {
181            if (volume >= 0 && volume <= VOLUME_MAX) {
182                mVolume = volume;
183                Log.d(TAG, mRouteId + ": New volume is " + mVolume);
184                publishRoutes();
185            }
186        }
187
188        @Override
189        public boolean sendControlRequest(Intent intent, ControlRequestCallback callback) {
190            Log.d(TAG, mRouteId + ": Received control request " + intent);
191            if (intent.getAction().equals(MediaControlIntent.ACTION_PLAY)
192                    && intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
193                    && intent.getData() != null) {
194                mPlaybackCount +=1;
195
196                Uri uri = intent.getData();
197                Log.d(TAG, mRouteId + ": Received play request, uri=" + uri);
198                Toast.makeText(getContext(), "Route received play request: uri=" + uri,
199                        Toast.LENGTH_LONG).show();
200                if (callback != null) {
201                    callback.onResult(ControlRequestCallback.REQUEST_SUCCEEDED, null);
202                }
203                return true;
204            }
205
206            if (intent.getAction().equals(ACTION_GET_STATISTICS)
207                    && intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) {
208                Bundle data = new Bundle();
209                data.putInt(DATA_PLAYBACK_COUNT, mPlaybackCount);
210                if (callback != null) {
211                    callback.onResult(ControlRequestCallback.REQUEST_SUCCEEDED, data);
212                }
213                return true;
214            }
215            return false;
216        }
217    }
218}