Home | History | Annotate | Download | only in com.example.android.basicmediarouter
      1 /*
      2  * Copyright 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.basicmediarouter;
     18 
     19 import android.app.Activity;
     20 import android.app.MediaRouteActionProvider;
     21 import android.content.Context;
     22 import android.content.DialogInterface;
     23 import android.media.MediaRouter;
     24 import android.media.MediaRouter.RouteInfo;
     25 import android.os.Bundle;
     26 import android.view.Display;
     27 import android.view.Menu;
     28 import android.view.MenuItem;
     29 import android.view.View;
     30 import android.view.WindowManager;
     31 import android.widget.Button;
     32 import android.widget.TextView;
     33 
     34 /**
     35  * <p>
     36  * This sample demonstrates the use of the MediaRouter API to show content on a
     37  * secondary display using a {@link android.app.Presentation}.
     38  * </p>
     39  * <p>
     40  * The activity uses the {@link android.media.MediaRouter} API to automatically detect when a
     41  * presentation display is available and to allow the user to control the media
     42  * routes using a menu item provided by the {@link android.app.MediaRouteActionProvider}.
     43  * When a presentation display is available a {@link android.app.Presentation} (implemented
     44  * as a {@link SamplePresentation}) is shown on the preferred display. A button
     45  * toggles the background color of the secondary screen to show the interaction
     46  * between the primary and secondary screens.
     47  * </p>
     48  * <p>
     49  * This sample requires an HDMI or Wifi display. Alternatively, the
     50  * "Simulate secondary displays" feature in Development Settings can be enabled
     51  * to simulate secondary displays.
     52  * </p>
     53  *
     54  * @see android.app.Presentation
     55  * @see android.media.MediaRouter
     56  */
     57 public class MainActivity extends Activity {
     58 
     59     private MediaRouter mMediaRouter;
     60 
     61     // Active Presentation, set to null if no secondary screen is enabled
     62     private SamplePresentation mPresentation;
     63 
     64     @Override
     65     protected void onCreate(Bundle savedInstanceState) {
     66         super.onCreate(savedInstanceState);
     67 
     68         setContentView(R.layout.sample_main);
     69         mTextStatus = (TextView) findViewById(R.id.textStatus);
     70 
     71         // get the list of background colors
     72         mColors = getResources().getIntArray(R.array.androidcolors);
     73 
     74         // Enable clicks on the 'change color' button
     75         mButton = (Button) findViewById(R.id.button1);
     76         mButton.setOnClickListener(new View.OnClickListener() {
     77 
     78             @Override
     79             public void onClick(View v) {
     80                 showNextColor();
     81             }
     82         });
     83 
     84         // BEGIN_INCLUDE(getMediaRouter)
     85         // Get the MediaRouter service
     86         mMediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);
     87         // END_INCLUDE(getMediaRouter)
     88     }
     89 
     90     /**
     91      * Implementing a {@link android.media.MediaRouter.Callback} to update the displayed
     92      * {@link android.app.Presentation} when a route is selected, unselected or the
     93      * presentation display has changed. The provided stub implementation
     94      * {@link android.media.MediaRouter.SimpleCallback} is extended and only
     95      * {@link android.media.MediaRouter.SimpleCallback#onRouteSelected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo)}
     96      * ,
     97      * {@link android.media.MediaRouter.SimpleCallback#onRouteUnselected(android.media.MediaRouter, int, android.media.MediaRouter.RouteInfo)}
     98      * and
     99      * {@link android.media.MediaRouter.SimpleCallback#onRoutePresentationDisplayChanged(android.media.MediaRouter, android.media.MediaRouter.RouteInfo)}
    100      * are overridden to update the displayed {@link android.app.Presentation} in
    101      * {@link #updatePresentation()}. These callbacks enable or disable the
    102      * second screen presentation based on the routing provided by the
    103      * {@link android.media.MediaRouter} for {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}
    104      * streams. @
    105      */
    106     private final MediaRouter.SimpleCallback mMediaRouterCallback =
    107             new MediaRouter.SimpleCallback() {
    108 
    109                 // BEGIN_INCLUDE(SimpleCallback)
    110                 /**
    111                  * A new route has been selected as active. Disable the current
    112                  * route and enable the new one.
    113                  */
    114                 @Override
    115                 public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
    116                     updatePresentation();
    117                 }
    118 
    119                 /**
    120                  * The route has been unselected.
    121                  */
    122                 @Override
    123                 public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
    124                     updatePresentation();
    125 
    126                 }
    127 
    128                 /**
    129                  * The route's presentation display has changed. This callback
    130                  * is called when the presentation has been activated, removed
    131                  * or its properties have changed.
    132                  */
    133                 @Override
    134                 public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
    135                     updatePresentation();
    136                 }
    137                 // END_INCLUDE(SimpleCallback)
    138             };
    139 
    140     /**
    141      * Updates the displayed presentation to enable a secondary screen if it has
    142      * been selected in the {@link android.media.MediaRouter} for the
    143      * {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO} type. If no screen has been
    144      * selected by the {@link android.media.MediaRouter}, the current screen is disabled.
    145      * Otherwise a new {@link SamplePresentation} is initialized and shown on
    146      * the secondary screen.
    147      */
    148     private void updatePresentation() {
    149 
    150         // BEGIN_INCLUDE(updatePresentationInit)
    151         // Get the selected route for live video
    152         RouteInfo selectedRoute = mMediaRouter.getSelectedRoute(
    153                 MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
    154 
    155         // Get its Display if a valid route has been selected
    156         Display selectedDisplay = null;
    157         if (selectedRoute != null) {
    158             selectedDisplay = selectedRoute.getPresentationDisplay();
    159         }
    160         // END_INCLUDE(updatePresentationInit)
    161 
    162         // BEGIN_INCLUDE(updatePresentationDismiss)
    163         /*
    164          * Dismiss the current presentation if the display has changed or no new
    165          * route has been selected
    166          */
    167         if (mPresentation != null && mPresentation.getDisplay() != selectedDisplay) {
    168             mPresentation.dismiss();
    169             mPresentation = null;
    170             mButton.setEnabled(false);
    171             mTextStatus.setText(R.string.secondary_notconnected);
    172         }
    173         // END_INCLUDE(updatePresentationDismiss)
    174 
    175         // BEGIN_INCLUDE(updatePresentationNew)
    176         /*
    177          * Show a new presentation if the previous one has been dismissed and a
    178          * route has been selected.
    179          */
    180         if (mPresentation == null && selectedDisplay != null) {
    181 
    182             // Initialise a new Presentation for the Display
    183             mPresentation = new SamplePresentation(this, selectedDisplay);
    184             mPresentation.setOnDismissListener(mOnDismissListener);
    185 
    186             // Try to show the presentation, this might fail if the display has
    187             // gone away in the mean time
    188             try {
    189                 mPresentation.show();
    190                 mTextStatus.setText(getResources().getString(R.string.secondary_connected,
    191                         selectedRoute.getName(MainActivity.this)));
    192                 mButton.setEnabled(true);
    193                 showNextColor();
    194             } catch (WindowManager.InvalidDisplayException ex) {
    195                 // Couldn't show presentation - display was already removed
    196                 mPresentation = null;
    197             }
    198         }
    199         // END_INCLUDE(updatePresentationNew)
    200 
    201     }
    202 
    203     @Override
    204     protected void onResume() {
    205         super.onResume();
    206 
    207         // BEGIN_INCLUDE(addCallback)
    208         // Register a callback for all events related to live video devices
    209         mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback);
    210         // END_INCLUDE(addCallback)
    211 
    212         // Show the 'Not connected' status message
    213         mButton.setEnabled(false);
    214         mTextStatus.setText(R.string.secondary_notconnected);
    215 
    216         // Update the displays based on the currently active routes
    217         updatePresentation();
    218     }
    219 
    220     @Override
    221     protected void onPause() {
    222         super.onPause();
    223 
    224         // BEGIN_INCLUDE(onPause)
    225         // Stop listening for changes to media routes.
    226         mMediaRouter.removeCallback(mMediaRouterCallback);
    227         // END_INCLUDE(onPause)
    228     }
    229 
    230     @Override
    231     protected void onStop() {
    232         super.onStop();
    233 
    234         // BEGIN_INCLUDE(onStop)
    235         // Dismiss the presentation when the activity is not visible.
    236         if (mPresentation != null) {
    237             mPresentation.dismiss();
    238             mPresentation = null;
    239         }
    240         // BEGIN_INCLUDE(onStop)
    241     }
    242 
    243     /**
    244      * Inflates the ActionBar or options menu. The menu file defines an item for
    245      * the {@link android.app.MediaRouteActionProvider}, which is registered here for all
    246      * live video devices using {@link android.media.MediaRouter#ROUTE_TYPE_LIVE_VIDEO}.
    247      */
    248     @Override
    249     public boolean onCreateOptionsMenu(Menu menu) {
    250         super.onCreateOptionsMenu(menu);
    251 
    252         getMenuInflater().inflate(R.menu.main, menu);
    253 
    254         // BEGIN_INCLUDE(MediaRouteActionProvider)
    255         // Configure the media router action provider
    256         MenuItem mediaRouteMenuItem = menu.findItem(R.id.menu_media_route);
    257         MediaRouteActionProvider mediaRouteActionProvider =
    258                 (MediaRouteActionProvider) mediaRouteMenuItem.getActionProvider();
    259         mediaRouteActionProvider.setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
    260         // BEGIN_INCLUDE(MediaRouteActionProvider)
    261 
    262         return true;
    263     }
    264 
    265     /**
    266      * Listens for dismissal of the {@link SamplePresentation} and removes its
    267      * reference.
    268      */
    269     private final DialogInterface.OnDismissListener mOnDismissListener =
    270             new DialogInterface.OnDismissListener() {
    271                 @Override
    272                 public void onDismiss(DialogInterface dialog) {
    273                     if (dialog == mPresentation) {
    274                         mPresentation = null;
    275                     }
    276                 }
    277             };
    278 
    279     // Views used to display status information on the primary screen
    280     private TextView mTextStatus;
    281     private Button mButton;
    282 
    283     // selected color index
    284     private int mColor = 0;
    285 
    286     // background colors
    287     public int[] mColors;
    288 
    289     /**
    290      * Displays the next color on the secondary screen if it is activate.
    291      */
    292     private void showNextColor() {
    293         if (mPresentation != null) {
    294             // a second screen is active and initialized, show the next color
    295             mPresentation.setColor(mColors[mColor]);
    296             mColor = (mColor + 1) % mColors.length;
    297         }
    298     }
    299 
    300 }
    301