• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.example.android.supportv7.media;
18 
19 import com.example.android.supportv7.R;
20 
21 import android.content.Intent;
22 import android.net.Uri;
23 import android.os.Bundle;
24 import android.support.v4.app.FragmentManager;
25 import android.support.v4.view.MenuItemCompat;
26 import android.support.v7.app.ActionBarActivity;
27 import android.support.v7.app.MediaRouteActionProvider;
28 import android.support.v7.app.MediaRouteDiscoveryFragment;
29 import android.support.v7.media.MediaControlIntent;
30 import android.support.v7.media.MediaRouter;
31 import android.support.v7.media.MediaRouter.Callback;
32 import android.support.v7.media.MediaRouter.RouteInfo;
33 import android.support.v7.media.MediaRouter.ProviderInfo;
34 import android.support.v7.media.MediaRouteSelector;
35 import android.util.Log;
36 import android.view.Menu;
37 import android.view.MenuItem;
38 import android.view.View;
39 import android.view.View.OnClickListener;
40 import android.widget.AdapterView.OnItemClickListener;
41 import android.widget.AdapterView;
42 import android.widget.ArrayAdapter;
43 import android.widget.Button;
44 import android.widget.ListView;
45 import android.widget.TextView;
46 import android.widget.Toast;
47 
48 /**
49  * <h3>Media Router Support Activity</h3>
50  *
51  * <p>
52  * This demonstrates how to use the {@link MediaRouter} API to build an
53  * application that allows the user to send content to various rendering
54  * targets.
55  * </p>
56  */
57 public class SampleMediaRouterActivity extends ActionBarActivity {
58     private static final String TAG = "MediaRouterSupport";
59     private static final String DISCOVERY_FRAGMENT_TAG = "DiscoveryFragment";
60 
61     private MediaRouter mMediaRouter;
62     private MediaRouteSelector mSelector;
63     private ArrayAdapter<MediaItem> mMediaItems;
64     private TextView mInfoTextView;
65     private ListView mMediaListView;
66     private Button mPlayButton;
67     private Button mStatisticsButton;
68 
69     @Override
onCreate(Bundle savedInstanceState)70     protected void onCreate(Bundle savedInstanceState) {
71         // Be sure to call the super class.
72         super.onCreate(savedInstanceState);
73 
74         // Get the media router service.
75         mMediaRouter = MediaRouter.getInstance(this);
76 
77         // Create a route selector for the type of routes that we care about.
78         mSelector = new MediaRouteSelector.Builder()
79                 .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
80                 .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
81                 .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
82                 .addControlCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE)
83                 .build();
84 
85         // Add a fragment to take care of media route discovery.
86         // This fragment automatically adds or removes a callback whenever the activity
87         // is started or stopped.
88         FragmentManager fm = getSupportFragmentManager();
89         if (fm.findFragmentByTag(DISCOVERY_FRAGMENT_TAG) == null) {
90             DiscoveryFragment fragment = new DiscoveryFragment();
91             fragment.setRouteSelector(mSelector);
92             fm.beginTransaction()
93                     .add(fragment, DISCOVERY_FRAGMENT_TAG)
94                     .commit();
95         }
96 
97         // Populate an array adapter with fake media items.
98         String[] mediaNames = getResources().getStringArray(R.array.media_names);
99         String[] mediaUris = getResources().getStringArray(R.array.media_uris);
100         mMediaItems = new ArrayAdapter<MediaItem>(this,
101                 android.R.layout.simple_list_item_single_choice, android.R.id.text1);
102         for (int i = 0; i < mediaNames.length; i++) {
103             mMediaItems.add(new MediaItem(mediaNames[i], Uri.parse(mediaUris[i])));
104         }
105 
106         // Initialize the layout.
107         setContentView(R.layout.sample_media_router);
108 
109         mInfoTextView = (TextView)findViewById(R.id.info);
110 
111         mMediaListView = (ListView)findViewById(R.id.media);
112         mMediaListView.setAdapter(mMediaItems);
113         mMediaListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
114         mMediaListView.setOnItemClickListener(new OnItemClickListener() {
115             @Override
116             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
117                 updateButtons();
118             }
119         });
120 
121         mPlayButton = (Button)findViewById(R.id.play_button);
122         mPlayButton.setOnClickListener(new OnClickListener() {
123             @Override
124             public void onClick(View v) {
125                 play();
126             }
127         });
128 
129         mStatisticsButton = (Button)findViewById(R.id.statistics_button);
130         mStatisticsButton.setOnClickListener(new OnClickListener() {
131             @Override
132             public void onClick(View v) {
133                 showStatistics();
134             }
135         });
136     }
137 
138     @Override
onStart()139     public void onStart() {
140         // Be sure to call the super class.
141         super.onStart();
142 
143         updateRouteDescription();
144     }
145 
146     @Override
onCreateOptionsMenu(Menu menu)147     public boolean onCreateOptionsMenu(Menu menu) {
148         // Be sure to call the super class.
149         super.onCreateOptionsMenu(menu);
150 
151         // Inflate the menu and configure the media router action provider.
152         getMenuInflater().inflate(R.menu.sample_media_router_menu, menu);
153 
154         MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
155         MediaRouteActionProvider mediaRouteActionProvider =
156                 (MediaRouteActionProvider)MenuItemCompat.getActionProvider(mediaRouteMenuItem);
157         mediaRouteActionProvider.setRouteSelector(mSelector);
158 
159         // Return true to show the menu.
160         return true;
161     }
162 
updateRouteDescription()163     private void updateRouteDescription() {
164         RouteInfo route = mMediaRouter.getSelectedRoute();
165         mInfoTextView.setText("Currently selected route: " + route.getName()
166                 + " from provider " + route.getProvider().getPackageName()
167                 + ", description: " + route.getDescription());
168         updateButtons();
169     }
170 
updateButtons()171     private void updateButtons() {
172         MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
173 
174         MediaItem item = getCheckedMediaItem();
175         if (item != null) {
176             mPlayButton.setEnabled(route.supportsControlRequest(makePlayIntent(item)));
177         } else {
178             mPlayButton.setEnabled(false);
179         }
180 
181         mStatisticsButton.setEnabled(route.supportsControlRequest(makeStatisticsIntent()));
182     }
183 
play()184     private void play() {
185         final MediaItem item = getCheckedMediaItem();
186         if (item == null) {
187             return;
188         }
189 
190         MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
191         Intent intent = makePlayIntent(item);
192         if (route.supportsControlRequest(intent)) {
193             MediaRouter.ControlRequestCallback callback =
194                     new MediaRouter.ControlRequestCallback() {
195                 @Override
196                 public void onResult(Bundle data) {
197                     String streamId = data != null ? data.getString(
198                             MediaControlIntent.EXTRA_ITEM_ID) : null;
199 
200                     Log.d(TAG, "Play request succeeded: data=" + data + " , streamId=" + streamId);
201                     Toast.makeText(SampleMediaRouterActivity.this,
202                             "Now playing " + item.mName,
203                             Toast.LENGTH_LONG).show();
204                 }
205 
206                 @Override
207                 public void onError(String error, Bundle data) {
208                     Log.d(TAG, "Play request failed: error=" + error + ", data=" + data);
209                     Toast.makeText(SampleMediaRouterActivity.this,
210                             "Unable to play " + item.mName + ", error: " + error,
211                             Toast.LENGTH_LONG).show();
212                 }
213             };
214 
215             Log.d(TAG, "Sending play request: intent=" + intent);
216             route.sendControlRequest(intent, callback);
217         } else {
218             Log.d(TAG, "Play request not supported: intent=" + intent);
219             Toast.makeText(SampleMediaRouterActivity.this,
220                     "Play not supported for " + item.mName, Toast.LENGTH_LONG).show();
221         }
222     }
223 
showStatistics()224     private void showStatistics() {
225         MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
226         Intent intent = makeStatisticsIntent();
227         if (route.supportsControlRequest(intent)) {
228             MediaRouter.ControlRequestCallback callback = new MediaRouter.ControlRequestCallback() {
229                 @Override
230                 public void onResult(Bundle data) {
231                     Log.d(TAG, "Statistics request succeeded: data=" + data);
232                     if (data != null) {
233                         int playbackCount = data.getInt(
234                                 SampleMediaRouteProvider.DATA_PLAYBACK_COUNT, -1);
235                         Toast.makeText(SampleMediaRouterActivity.this,
236                                 "Total playback count: " + playbackCount,
237                                 Toast.LENGTH_LONG).show();
238                     } else {
239                         Toast.makeText(SampleMediaRouterActivity.this,
240                                 "Statistics query did not return any data",
241                                 Toast.LENGTH_LONG).show();
242                     }
243                 }
244 
245                 @Override
246                 public void onError(String error, Bundle data) {
247                     Log.d(TAG, "Statistics request failed: error=" + error + ", data=" + data);
248                     Toast.makeText(SampleMediaRouterActivity.this,
249                             "Unable to query statistics, error: " + error,
250                             Toast.LENGTH_LONG).show();
251                 }
252             };
253 
254             Log.d(TAG, "Sent statistics request: intent=" + intent);
255             route.sendControlRequest(intent, callback);
256         } else {
257             Log.d(TAG, "Statistics request not supported: intent=" + intent);
258             Toast.makeText(SampleMediaRouterActivity.this,
259                     "Statistics not supported.", Toast.LENGTH_LONG).show();
260         }
261     }
262 
makePlayIntent(MediaItem item)263     private Intent makePlayIntent(MediaItem item) {
264         Intent intent = new Intent(MediaControlIntent.ACTION_PLAY);
265         intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
266         intent.setDataAndType(item.mUri, "video/mp4");
267         return intent;
268     }
269 
makeStatisticsIntent()270     private Intent makeStatisticsIntent() {
271         Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_STATISTICS);
272         intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE);
273         return intent;
274     }
275 
getCheckedMediaItem()276     private MediaItem getCheckedMediaItem() {
277         int index = mMediaListView.getCheckedItemPosition();
278         if (index >= 0 && index < mMediaItems.getCount()) {
279             return mMediaItems.getItem(index);
280         }
281         return null;
282     }
283 
284     private final class DiscoveryFragment extends MediaRouteDiscoveryFragment {
285         @Override
onCreateCallback()286         public Callback onCreateCallback() {
287             // Return a custom callback that will simply log all of the route events
288             // for demonstration purposes.
289             return new MediaRouter.Callback() {
290                 @Override
291                 public void onRouteAdded(MediaRouter router, RouteInfo route) {
292                     Log.d(TAG, "onRouteAdded: route=" + route);
293                 }
294 
295                 @Override
296                 public void onRouteChanged(MediaRouter router, RouteInfo route) {
297                     Log.d(TAG, "onRouteChanged: route=" + route);
298                     updateRouteDescription();
299                 }
300 
301                 @Override
302                 public void onRouteRemoved(MediaRouter router, RouteInfo route) {
303                     Log.d(TAG, "onRouteRemoved: route=" + route);
304                 }
305 
306                 @Override
307                 public void onRouteSelected(MediaRouter router, RouteInfo route) {
308                     Log.d(TAG, "onRouteSelected: route=" + route);
309                     updateRouteDescription();
310                 }
311 
312                 @Override
313                 public void onRouteUnselected(MediaRouter router, RouteInfo route) {
314                     Log.d(TAG, "onRouteUnselected: route=" + route);
315                     updateRouteDescription();
316                 }
317 
318                 @Override
319                 public void onRouteVolumeChanged(MediaRouter router, RouteInfo route) {
320                     Log.d(TAG, "onRouteVolumeChanged: route=" + route);
321                 }
322 
323                 @Override
324                 public void onRoutePresentationDisplayChanged(
325                         MediaRouter router, RouteInfo route) {
326                     Log.d(TAG, "onRoutePresentationDisplayChanged: route=" + route);
327                 }
328 
329                 @Override
330                 public void onProviderAdded(MediaRouter router, ProviderInfo provider) {
331                     Log.d(TAG, "onRouteProviderAdded: provider=" + provider);
332                 }
333 
334                 @Override
335                 public void onProviderRemoved(MediaRouter router, ProviderInfo provider) {
336                     Log.d(TAG, "onRouteProviderRemoved: provider=" + provider);
337                 }
338 
339                 @Override
340                 public void onProviderChanged(MediaRouter router, ProviderInfo provider) {
341                     Log.d(TAG, "onRouteProviderChanged: provider=" + provider);
342                 }
343             };
344         }
345 
346         @Override
onPrepareCallbackFlags()347         public int onPrepareCallbackFlags() {
348             // Add the CALLBACK_FLAG_UNFILTERED_EVENTS flag to ensure that we will
349             // observe and log all route events including those that are for routes
350             // that do not match our selector.  This is only for demonstration purposes
351             // and should not be needed by most applications.
352             return super.onPrepareCallbackFlags()
353                     | MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS;
354         }
355     }
356 
357     private static final class MediaItem {
358         public final String mName;
359         public final Uri mUri;
360 
361         public MediaItem(String name, Uri uri) {
362             mName = name;
363             mUri = uri;
364         }
365 
366         @Override
367         public String toString() {
368             return mName;
369         }
370     }
371 
372     /**
373      * Trivial subclass of this activity used to provide another copy of the
374      * same activity using a light theme instead of the dark theme.
375      */
376     public static class Light extends SampleMediaRouterActivity {
377     }
378 
379     /**
380      * Trivial subclass of this activity used to provide another copy of the
381      * same activity using a light theme with dark action bar instead of the dark theme.
382      */
383     public static class LightWithDarkActionBar extends SampleMediaRouterActivity {
384     }
385 }
386