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}