VideoView

Tap the black VideoView to display its controls. Then tap the triangular Run button in these controls to watch Fred Ott’s Sneeze.

We’ve seen a TextView and an ImageView. Now it’s time for a VideoView. See View the Video.

Source code in VideoView.zip

  1. MainActivity.java launches other activities.
  2. activity_main.xml contains a VideoView.
  3. strings.xml
  4. a0026a.mp4 is on the list of Supported Media Formats.
  5. AndroidManifest.xml
  6. build.gradle (Module: app)

Create the project

Select the app/res folder in the Android Studio project view and pull down
File → New → Android resource directory
Resource type: raw
OK

Point your browser at Edison kinetoscopic record of a sneeze, January 7, 1894 at the Library of Congress. In the lower left, under Resources, download the MP4. Download it as a0026a.mp4, not 0026a.mp4. Copy and paste the file into the app’s app/res/raw folder. The id number of this file will be stored into the variable R.raw.a0026a. It would be impossible in Java to have a variable named R.raw.0026a.

Run the project on the Genymotion emulator

Turn up the Mac or PC sound volume before launching the app.

VideoView in ApiDemos:
Media → VideoView

  1. VideoViewDemo.java defines a subclass of class Activity.
  2. videoview.xml contains a VideoView.
  3. videoviewdemo.mp4. Click on View Raw to download the .mp4 file.

Things to try

  1. You can run the video without any controls. Change
            videoView.setMediaController(new MediaController(this));
    
    to
            videoView.start(); //Start the video spontaneously.
    

  2. Play the video file in an infinite loop. Append the following to onCreate. This is one way to get your hands on the MediaPlayer inside the VideoView. The variable videoView will have to be declared final.
            videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    videoView.seekTo(0); //milliseconds; 0 is the start of the file
                    videoView.start();
                }
            });
    
    Or seek to 7000 milliseconds to skip the intro.

  3. Print the duration and dimensions of the video.
            videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    Log.d("myTag", "duration = " + mediaPlayer.getDuration() + " milliseconds");
                    Log.d("myTag", "dimensions = (" + mediaPlayer.getVideoWidth() + ", " + mediaPlayer.getVideoHeight() + ")");
                    mediaPlayer.setLooping(true); //Another way to go into an infinite loop.
                }
            });
    
    08-20 22:26:59.999    3426-3426/? D/myTag: duration = 22733 milliseconds
    08-20 22:26:59.999    3426-3426/? D/myTag: dimensions = (480, 360)
    
    And now that you know the dimensions in pixels, you could change the width and height of the VideoView in activity_main.xml to 480px by 360px if you wanted to watch the video at its actual size. See also MediaPlayer.OnVideoSizeChangedListener.

  4. Play a video from the web. Change the Uri to
            Uri uri = Uri.parse("http://stream.media.loc.gov/ammem/EdisonCompanies/0026a.mp4");
    
    and add the following element to the <manifest> element in AndroidManifest.xml.
        <uses-permission android:name="android.permission.INTERNET"/>
    

  5. Two other ways to play a video:
    1. With a WebView.
          <uses-permission android:name="android.permission.INTERNET"/>
      

      Attribute of <activity> element:

              android:hardwareAccelerated="true"
      
          <WebView
              android:id="@+id/webView"
              android:layout_width="match_parent"
              android:layout_height="match_parent"/>
      
              WebView webView = (WebView)findViewById(R.id.webView);
              WebSettings webSettings = webView.getSettings();
              webSettings.setJavaScriptEnabled(true);
              webSettings.setAllowFileAccess(true);
      
              //Allow the JavaScript program to display an alert window.
              webView.setWebViewClient(new WebViewClient());
              webView.setWebChromeClient(new WebChromeClient());
              webView.loadUrl("http://stream.media.loc.gov/ammem/EdisonCompanies/0026a.mp4");
      
      On my Amazon HD6 fire and on my Nexus 5 API 22 Android Virtual Device, the WebView worked correctly. On the Genymotion Samsung Galaxy S5, the WebView displayed controls and played the sound but gave me a black screen. The error messages included the following.
      08-23 09:54:05.292    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder_autogen.h(1082)] [GroupMarkerNotSet(crbug.com/242999)!:0075F2B7]GL ERROR :GL_INVALID_OPERATION : GetIntegerv: <- error from previous GL command
      08-23 09:54:05.308    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder_autogen.h(1082)] [GroupMarkerNotSet(crbug.com/242999)!:807CF6B7]GL ERROR :GL_INVALID_OPERATION : GetIntegerv: <- error from previous GL command
      08-23 09:54:05.328    3307-3307/? E/eglCodecCommon﹕ **** ERROR unknown type 0xb7ef9518 (glSizeof,80)
      08-23 09:54:10.336    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder_autogen.h(1082)] [GroupMarkerNotSet(crbug.com/242999)!:30F1FAB7]GL ERROR :GL_INVALID_OPERATION : GetIntegerv: <- error from previous GL command
      08-23 09:54:10.408    3307-3307/? E/eglCodecCommon﹕ **** ERROR unknown type 0xb7ef9518 (glSizeof,80)
      08-23 09:54:10.860    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(5942)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_INVALID_OPERATION : glUseProgram: program not linked
      08-23 09:54:10.860    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(5718)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_INVALID_OPERATION : glUniformMatrix4fv: wrong uniform function for type
      08-23 09:54:10.860    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(5718)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_INVALID_OPERATION : glUniform1iv: wrong uniform function for type
      08-23 09:54:10.860    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(1777)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_OUT_OF_MEMORY : GLES2DecoderImpl::PrepareTexturesForRender: <- error from previous GL command
      08-23 09:54:15.572    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(5942)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_INVALID_OPERATION : glUseProgram: program not linked
      08-23 09:54:15.572    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(5718)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_INVALID_OPERATION : glUniformMatrix4fv: wrong uniform function for type
      08-23 09:54:15.572    3307-3307/? E/chromium﹕ [ERROR:gles2_cmd_decoder.cc(5718)] [.Compositor-Onscreen-0xb7f69378]GL ERROR :GL_INVALID_OPERATION : glUniform1iv: wrong uniform function for type
      08-23 09:54:15.580    3307-3307/? E/eglCodecCommon﹕ **** ERROR unknown type 0xb7ef9518 (glSizeof,80)
      08-23 09:54:16.084    3307-3307/? E/eglCodecCommon﹕ **** ERROR unknown type 0xb7ef9518 (glSizeof,80)
      
      This article from May 11, 2015 might explain why WebViews crash when displaying videos.
    2. Use an Intent to find and launch a video-playing Activity. I got this to work for videos downloaded from the Internet (http://), but not for videos in the app/res/raw or app/assets folders.
              Uri uri = Uri.parse("http://stream.media.loc.gov/ammem/EdisonCompanies/0026a.mp4");
              Intent intent = new Intent(Intent.ACTION_VIEW);
              intent.setDataAndType(uri, "video/*");
              startActivity(intent);