Insider's Guide To Udacity Android Developer Nanodegree Part 3 - Making the Baking App
Insider's Guide To Udacity Android Developer Nanodegree Part 3 - Making the Baking App
Written by Nikos Vaggalis   
Monday, 03 July 2017
Article Index
Insider's Guide To Udacity Android Developer Nanodegree Part 3 - Making the Baking App
Step 1 - Fragments
Fragments In Action
Layouts
Fragments
Step 2 - Libraries & Networking
POJO To Parcelables
Step 3 - Adding Exoplayer
Step 4 - Widgets
Step 5 - The Widget Provider
Step 6 - UI Testing
Step 7 - Testing Intents



Step 3 - Adding Exoplayer

In this step I'm going to satisfy the following three requirements:

  • Application uses Exoplayer to display videos.

  • Application should properly retrieve media assets from the provided network links. It should properly handle network requests.

  • Application properly initializes and releases video assets when appropriate.


Two components are required to play video and audio on the Android platform: the Media Player, the component which takes the digital media and renders it as audio or video; and the Media Controller, the piece of UI that has the playback buttons which you can control the Media Player with.

image16a

 

While the framework provides a MediaPlayer implementation this comes with basic functionality and few customization options. However, the lesson utilizes the Exoplayer library, which offers rich customization and advanced features. An Exoplayer instance should be instatiated within the RecipeStepDetailFragment, the fragment that is responsible for displaying the videos.
        
First set up an Exoplayer view, the container in which the media will play: 

 
 simpleExoPlayerView =
     (SimpleExoPlayerView) rootView.findViewById(R.id.playerView);
 simpleExoPlayerView.setResizeMode(
                              AspectRatioFrameLayout.RESIZE_MODE_FIT);

 

Then call the step's object getter method getVideoURL() to get the URL pointing to the media file, always checking that in fact there's a URL:

 

 
  String videoURL = steps.get(selectedIndex).getVideoURL();
  if (!videoURL.isEmpty()) {
 

 

If there's a URL, initialize the actual player object by calling:

 

 
 initializePlayer(Uri.parse(steps.get(selectedIndex).getVideoURL()));


which takes care of the media player and controller talked about earlier:

 


private void initializePlayer(Uri mediaUri) {
        if (player == null) {
            TrackSelection.Factory videoTrackSelectionFactory =
              new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
            DefaultTrackSelector trackSelector =
              new DefaultTrackSelector(mainHandler,
                                              videoTrackSelectionFactory);
            LoadControl loadControl = new DefaultLoadControl();

            player = ExoPlayerFactory.newSimpleInstance(
                                    getContext(), trackSelector, loadControl);
            simpleExoPlayerView.setPlayer(player);

            String userAgent = Util.getUserAgent(getContext(),
                                                                            "Baking App");
            MediaSource mediaSource =
                           new ExtractorMediaSource(mediaUri,
                           new DefaultDataSourceFactory(getContext(),
                           userAgent),
                           new DefaultExtractorsFactory(), null, null);
            player.prepare(mediaSource);
            player.setPlayWhenReady(true);
        }
    }


After initializing and fetching the media file from the network, the code resumes in the part that resizes the player depending on the device/layout in effect.So if on a Tablet and Landscape:


 if (rootView.findViewWithTag("sw600dp-land-recipe_step_detail")!=
                                               null) {
 


resize the fragment to its full width potential:                 
   


getActivity().findViewById(R.id.fragment_container2)
            .setLayoutParams(new LinearLayout.LayoutParams(-1,-2));
   


and force the ExoPlayerView instance, simpleExoPlayerView, to occupy that space: 

 
simpleExoPlayerView.setResizeMode(
           AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH);                

 

image17
In case there's no video to display, but just instructions in textual form, I set up a small 300x300 area in which to display an icon suggesting that there's no video to display, to preserve a consistent UI experience and offer a uniform user interface no matter the size and orientation of the device. This icon will always be 36dp wide and occupy a 300x300dp box
 

simpleExoPlayerView.setForeground(
                                 ContextCompat.getDrawable(getContext(),
                                           R.drawable.ic_visibility_off_white_36dp));
simpleExoPlayerView.setLayoutParams(
                                      new LinearLayout.LayoutParams(300, 300));
       

 

image18        
The last thing remaining is to release the acquired video resources at the appropriate stages of the fragment's lifecycle such as onDetach


@Override
    public void onDetach() {
        super.onDetach();
        if (player!=null) {
            player.stop();
            player.release();
        }
    }


The same goes for onDestroyView, onStop and onPause.  

 



Last Updated ( Tuesday, 04 July 2017 )
 
 

   
Banner
Banner
RSS feed of all content
I Programmer - full contents
Copyright © 2017 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.