Android 4
24. Media - Part B
This chapter
Now, let's look at another class for audio play, MyAudioPlayer.java:
package com.bogotobogo.android.audiovideo; import android.app.Activity; import android.media.MediaPlayer; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class MyAudioPlayer extends Activity { private static final String TAG = "AudioVideo"; private MediaPlayer mMediaPlayer; private static final String AUDIOVIDEO = "audiovideo"; private static final int LOCAL_AUDIO = 1; private static final int STREAM_AUDIO = 2; private static final int RESOURCES_AUDIO = 3; private String path; private TextView tx; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); tx = new TextView(this); setContentView(tx); Bundle extras = getIntent().getExtras(); playAudio(extras.getInt(AUDIOVIDEO)); } private void playAudio(Integer media) { try { switch (media) { case LOCAL_AUDIO: /** * TODO: Set the path variable to a local audio file path. */ path = "/sdcard/sample.mp3"; mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path); mMediaPlayer.prepare(); mMediaPlayer.start(); break; case RESOURCES_AUDIO: /** * TODO: Upload a audio file to res/raw folder and provide * its reside in MediaPlayer.create() method. */ mMediaPlayer = MediaPlayer.create(this, R.raw.sample); mMediaPlayer.start(); case STREAM_AUDIO: path = "http://www.bogotobogo.com/Audio/sample.mp3"; mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path); mMediaPlayer.prepare(); mMediaPlayer.start(); break; } tx.setText("Playing audio..."); } catch (Exception e) { Log.e(TAG, "error: " + e.getMessage(), e); } } @Override protected void onDestroy() { super.onDestroy(); // TODO Auto-generated method stub if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } } }
There are a number of ways we can play an audio content through the Media Player. We can include it as an application resource, play it from local files or Content Providers, or stream it from a remote server.
We can include audio file in out application package by adding them to the /res/raw folder of our resources. Raw resources are not compressed or manipulated in any way when packaged into our application, making them an ideal way to store pre-compressed files such as audio content.
To access a raw resource simple use the lowercase filename without an extension:
context appContext = getApplicationContext(); MediaPlayer resourcePlayer = MediaPlayer.create(appContext, R.raw.my_audio);
In our code, it is:
mMediaPlayer = MediaPlayer.create(this, R.raw.sample);
There are other ways of initializing audio content for playback:
MediaPlayer filePlayer = MediaPlayer.create(appContext, Uri.parse("file:///sdcard/localsdfile.mp3"));
MediaPlayer urlPlayer = MediaPlayer.create(appContext, Uri.parse("http://www.mysite.com/myfile.mp3"));
MediaPlayer contentPlayer = MediaPlayer.create(appContext, Settings.System.DEFAULT_RINGTONE_URI);
Alternatively, we can use the setDataSource() method on an existing Media Player instance. This method accepts a file path, Content Provider URI, streaming media URL path, or File Descripter. When using the the setDataSource() method it is vital that we call prepare() on the Media Player before we begin playback as in our code:
path = "/sdcard/sample.mp3"; mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path); mMediaPlayer.prepare();
To show a video, we must specify a display surface on which to show it. There are two ways for the playback of video content. The first one is using the Video View control and we handled this in the section 24.1 VideoView.
The second way allows us to specify our own display surface and manipulate the underlying Media Player instance directly.
The first step to using the Media Player to view video content is to prepare a Surface onto which the video will be displayed. The Media Player requires a SurfaceHolder object for displaying video content, assigned using the setDisplay() method.
To include a Surface Holder in our UI layout, we use the SurfaceView control as in the file, mediaplayer_2.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <SurfaceView android:id="@+id/surface" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center"> </SurfaceView> </LinearLayout>
The Surface View is a wrapper around the Surface Holder object.
Let's look at our code for video play, MyVideoPlayer.java:
package com.bogotobogo.android.audiovideo; import android.app.Activity; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnBufferingUpdateListener; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnPreparedListener; import android.media.MediaPlayer.OnVideoSizeChangedListener; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class MyVideoPlayer extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback { private static final String TAG = "AudioVideo"; private int mVideoWidth; private int mVideoHeight; private MediaPlayer mMediaPlayer; private SurfaceView mPreview; private SurfaceHolder holder; private String path; private Bundle extras; private static final String AUDIOVIDEO = "audiovideo"; private static final int LOCAL_VIDEO = 4; private static final int STREAM_VIDEO = 5; private static final int RESOURCES_VIDEO = 6; private boolean mIsVideoSizeKnown = false; private boolean mIsVideoReadyToBePlayed = false; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.mediaplayer_2); mPreview = (SurfaceView) findViewById(R.id.surface); holder = mPreview.getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); extras = getIntent().getExtras(); } private void playVideo(Integer AUDIOVIDEO) { doCleanUp(); try { switch (AUDIOVIDEO) { case LOCAL_VIDEO: /* * TODO: Set the path variable to a local media file path. */ path = "/sdcard/sample.mov"; // Create a new media player and set the listeners mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path); mMediaPlayer.setDisplay(holder); mMediaPlayer.prepare(); mMediaPlayer.setOnBufferingUpdateListener(this); mMediaPlayer.setOnCompletionListener(this); mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.setOnVideoSizeChangedListener(this); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); break; case RESOURCES_VIDEO: /** * TODO: Upload a video file to res/raw folder */ mMediaPlayer = MediaPlayer.create(this, R.raw.samplemp4); mMediaPlayer.start(); case STREAM_VIDEO: /* * TODO: Set path variable to progressive streamable mp4 or * 3gpp format URL. Http protocol should be used. * Mediaplayer can only play "progressive streamable * contents" which basically means: 1. the movie atom has to * precede all the media data atoms. 2. The clip has to be * reasonably interleaved. * */ path = "http://www.bogotobogo.com/Video/sample.3gp"; // Create a new media player and set the listeners mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path); mMediaPlayer.setDisplay(holder); mMediaPlayer.prepare(); mMediaPlayer.setOnBufferingUpdateListener(this); mMediaPlayer.setOnCompletionListener(this); mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.setOnVideoSizeChangedListener(this); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); break; } } catch (Exception e) { Log.e(TAG, "error: " + e.getMessage(), e); } } public void onBufferingUpdate(MediaPlayer arg0, int percent) { Log.d(TAG, "onBufferingUpdate percent:" + percent); } public void onCompletion(MediaPlayer arg0) { Log.d(TAG, "onCompletion called"); } public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { Log.v(TAG, "onVideoSizeChanged called"); if (width == 0 || height == 0) { Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")"); return; } mIsVideoSizeKnown = true; mVideoWidth = width; mVideoHeight = height; if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { startVideoPlayback(); } } public void onPrepared(MediaPlayer mediaplayer) { Log.d(TAG, "onPrepared called"); mIsVideoReadyToBePlayed = true; if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { startVideoPlayback(); } } public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) { Log.d(TAG, "surfaceChanged called"); } public void surfaceDestroyed(SurfaceHolder surfaceholder) { Log.d(TAG, "surfaceDestroyed called"); } public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG, "surfaceCreated called"); playVideo(extras.getInt(AUDIOVIDEO)); } @Override protected void onPause() { super.onPause(); releaseMediaPlayer(); doCleanUp(); } @Override protected void onDestroy() { super.onDestroy(); releaseMediaPlayer(); doCleanUp(); } private void releaseMediaPlayer() { if (mMediaPlayer != null) { mMediaPlayer.release(); mMediaPlayer = null; } } private void doCleanUp() { mVideoWidth = 0; mVideoHeight = 0; mIsVideoReadyToBePlayed = false; mIsVideoSizeKnown = false; } private void startVideoPlayback() { Log.v(TAG, "startVideoPlayback"); holder.setFixedSize(mVideoWidth, mVideoHeight); mMediaPlayer.start(); } }
Note that we must implement the SurfaceHoler.Callback interface.
public class MyVideoPlayer extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {
Surface Holders are created asynchronously, so we must wait until the surfaceCreated handler has been fired before assigning the returned Surface Holder object to the Media Player.
Once we have created and assigned the Surface Holder to our Media Player, use the setDataSource() method to specify the path, URL, or Content Provider URI of the video resource to play.
path = "/sdcard/sample.mov"; // Create a new media player and set the listeners mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path); mMediaPlayer.setDisplay(holder); mMediaPlayer.prepare();
Once we've selected our media source, call prepare() to initialize the Media Player in preparation for playback.
After the Media Player is prepared, call start() to begin playback of the associated media:
public void onPrepared(MediaPlayer mediaplayer) { Log.d(TAG, "onPrepared called"); mIsVideoReadyToBePlayed = true; if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) { startVideoPlayback(); } } private void startVideoPlayback() { Log.v(TAG, "startVideoPlayback"); holder.setFixedSize(mVideoWidth, mVideoHeight); mMediaPlayer.start(); }
Files used in section 24.3-5 example,
AudioVideo.zip
Previous sections:
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization