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