CHP 15
CHP 15
1
Playing
audio and
video
2
Media Player
The playback of audio and video within Android applications is handled primarily
through the MediaPlayer class.
Using the Media Player, you can play media stored in application resources, local
files,
Content Providers, or streamed from a network URL.
The Media Player’s management of audio and video files and streams is handled as
a state machine.
In the most simplistic terms, transitions through the state machine can be described
as
follows:
1. Initialize the Media Player with media to play.
2. Prepare the Media Player for playback.
3. Start the playback.
4. Pause or stop the playback prior to its completing.
5. The playback is complete.
4
Initializing
Audio Content for
Playback
create a new Media Player object and
5
prepare();
The Media Player objects returned by these create methods have
already had prepare called. It’s important that you do not call it again.
Alternatively,
You 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 Descriptor.
When using the setDataSource method, it is vital that you call prepare on
the Media Player before you begin playback.
6
Preparing Video for Playback
To play a video, you first must have a Surface on which to show it.
There are two alternatives for the playback of video content.
The first technique, using the VideoView class, encapsulates
the creation of a Surface and allocation and preparation of
video content using a Media Player.
The second technique allows you to specify your own
Surface and manipulate the underlying Media Player instance
directly.
7
Playing Video Using the Video View
The simplest way to play back video is to use the Video View.
The Video View includes a Surface on which the video is displayed
and encapsulates and manages a Media Player instance that handles
the playback.
8
Video playback using a Video View
// Get a reference to the Video View.
final VideoView videoView =
(VideoView)findViewById(R.id.videoView);
// Configure the video view and assign a source video.
Methods of Video View
videoView.setKeepScreenOn(true);
videoView.setVideoPath(“/sdcard/mycatvideo.3gp”); setVideoPath()
setVideoUri()
// Attach a Media Controller start()
MediaController mediaController = new MediaController(this);
stopPlayback()
videoView.setMediaController(mediaController);
pause()
seekTo()
setKeepScreenOn()
9
Creating
a Surface for Video Playback
The first step for using the Media Player directly to view
video content is to prepare a Surface onto which the video
will be displayed.
This is generally handled using a SurfaceView object.
The Surface View class is a wrapper around the Surface
Holder object, which, in turn, is a wrapper around the Surface
that is used to support visual updates from background threads.
The Media Player uses a SurfaceHolder object to display video
content, assigned using the setDisplay method.
1
0
Sample layout using a Surface
View
<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout
<Button
android:id=”@+id/buttonPlay”
xmlns:android=”http://schemas.android android:layout_width=”wrap_content”
.com/apk/res/android” android:layout_height=”wrap_content”
android:layout_width=”match_parent” android:text=”Play” />
android:layout_height=”match_parent” <Button
android:orientation=”vertical” > android:id=”@+id/buttonPause”
android:layout_width=”wrap_content”
<SurfaceView android:layout_height=”wrap_content”
android:id=”@+id/surfaceView” android:text=”Pause” />
android:layout_width=”match_parent” <Button
android:layout_height=”match_parent” android:id=”@+id/buttonSkip”
android:layout_weight=”30” /> android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
<LinearLayout android:text=”Skip” />
android:id=”@+id/linearLayout1”
android:layout_width=”match_parent” </LinearLayout>
android:layout_height=”wrap_content”
android:layout_weight=”1”> </LinearLayout>
1
1
Initializing and assigning
a Surface View to a Media
Player
public class SurfaceViewVideoViewActivity extends Activity
implements SurfaceHolder.Callback
{
static final String TAG = “SurfaceViewVideoViewActivity”;
private MediaPlayer mediaPlayer;
public void surfaceCreated(SurfaceHolder holder) {
try {
mediaPlayer.setDisplay(holder);
mediaPlayer.setDataSource(“/sdcard/test2.3gp”);
mediaPlayer.prepare();
}
catch (Exception e) {
Log.e(TAG, “IO Exception“, e);
}
}
1
2
public void surfaceDestroyed(SurfaceHolder holder)
{ mediaPlayer.release();
}
public void surfaceChanged(SurfaceHolder holder,int
format, int width, int height) { }
@Override
public void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.surfaceviewvideoviewer);
mediaPlayer = new MediaPlayer(); // Create a new
Media Player.
// Get a reference to the Surface View.
final SurfaceView surfaceView
=(SurfaceView)findViewById(R.id.surfaceView);
surfaceView.setKeepScreenOn(true); // Configure the
Surface View.
// Configure the Surface Holder and register the callback.
SurfaceHolder holder = surfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.setFixedSize(400, 300);
14
BipinRupadiya.com
Controlling
Media Player Playback
// Attach a Media Controller
MediaController mediaController = new MediaController(this);
videoView.setMediaController(mediaController);
mediaController.setMediaPlayer(new MediaPlayerControl()
{
public boolean canPause() { return true; }
public boolean canSeekBackward() { return true; }
public boolean canSeekForward() { return true; }
public int getBufferPercentage() { return 0; }
1
5
setAnchorView()
Use the setAnchorView method to determine which view should
anchor the Media Controller when it’s visible, and call show or hide
to show or hide the controller, respectively:
mediaController.setAnchorView(myView);
mediaController.show();
Note that you must associate a Media Player Control
before attempting to display the Media Controller.
1
6
Managing
Media Playback Output
Control volume during playback using the setVolume().
It takes a scalar float value between 0 and 1 for both the left and right channels
(where 0 is silent and 1 is maximum volume).
mediaPlayer.setVolume(0.5f, 0.5f);
To force the screen to stay on during video playback,
mediaPlayer.setScreenOnWhilePlaying(true);
Use the isLooping() to determine the current loop status, and the setLooping()
to specify if the media being played should loop when it completes:
if (!mediaPlayer.isLooping())
mediaPlayer.setLooping(true);
1
7
Responding to the Volume Controls
It’s important that your application correctly handles, users
pressing
the volume and any attached media playback control keys.
By default, using the volume keys, on either the device or an
attached headset, changes the volume of whichever audio stream is
currently playing.
If no stream is active, the volume keys will alter the ringtone volume.
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.audioplayer);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
1
8
Responding to
the Media Playback Controls
If your application plays audio and/or video in a way users would associate
with
a media player, it should respond predictably to media button presses.
Some devices, as well as attached or Bluetooth headsets, feature play, stop,
pause, skip, and previous media playback keys.
When users press these keys, the system broadcasts an Intent with
the
ACTION_MEDIA_BUTTON action.
To receive this broadcast, you must have a Broadcast Receiver declared in
your manifest
<receiver that listens for this action
android:name=”.MediaControlReceiver”>
<intent-filter>
<action android:name=”android.intent.action.MEDIA_BUTTON”/>
</intent-filter>
</receiver>
1
9
A media button press Manifest
Broadcast Receiver implementation
public class MediaControlReceiver extends BroadcastReceiver
{ public static final String ACTION_MEDIA_BUTTON =
“com.paad.ACTION_MEDIA_BUTTON”;
@Override
public void onReceive(Context context, Intent intent)
{
if
(Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction
())) {
Intent internalIntent = new Intent(ACTION_MEDIA_BUTTON);
internalIntent.putExtras(intent.getExtras());
context.sendBroadcast(internalIntent);
}
}
} 2
0
Media button press
Broadcast Receiver
public class ActivityMediaControlReceiver extends BroadcastReceiver {
implementation
@Override
public void onReceive(Context context, Intent intent) {
if (MediaControlReceiver.ACTION_MEDIA_BUTTON.equals(intent.getAction()))
{ KeyEvent event
=(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); switch
(event.getKeyCode()) {
if (mediaPlayer.isPlaying()) {
case (KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) : pause(); } { play(); }
else break;
case (KeyEvent.KEYCODE_MEDIA_PLAY) :
play(); break;
case (KeyEvent.KEYCODE_MEDIA_PAUSE) :
pause(); break;
case (KeyEvent.KEYCODE_MEDIA_NEXT) :
skip(); break;
case (KeyEvent.KEYCODE_MEDIA_PREVIOUS) :
previous(); break;
case (KeyEvent.KEYCODE_MEDIA_STOP) :
stop(); break;
default: break;
}
}
}}
2
BipinRupadiya.com 1
MANIPULATING RAW AUDIO
The AudioTrack and AudioRecord classes let you record audio directly
from the audio input hardware and stream PCM audio buffers directly to
the audio hardware for playback.
2
BipinRupadiya.com 2
Recording
Sound with Audio Record
Use the AudioRecord class to record audio directly from the hardware buffers.
Create a new Audio Record object,
specifying the source,
frequency,
channel configuration,
audio encoding, and
buffer size
Android requires that the RECORD_AUDIO permission be included in your manifest:
<uses-permission android:name=”android.permission.RECORD_AUDIO”/>
Example:
Recording raw audio with Audio Record
2
BipinRupadiya.com 3
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
while (isRecording) {
int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++)
dos.writeShort(buffer[i]);
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.d(TAG, “An error occurred during recording”, t);
} 24
BipinRupadiya.com
Playing Sound with Audio Track
Use the AudioTrack class to play raw audio directly into the
hardware buffers.
Create a new Audio Track object, specifying the streaming
mode, frequency, channel configuration, and the audio encoding
type and length of the audio to play back:
Because this is raw audio, no metadata is associated with
the recorded files, so it’s important to correctly set the audio
data properties to the same values as those used when recording
the file.
After initializing your Audio Track, run the play method to
begin asynchronous playback, and use the write method to add
raw audio data into the playback buffer:
25
BipinRupadiya.com
int frequency = 11025/2;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
File file = new File(Environment.getExternalStorageDirectory(), “raw.pcm”);
// Short array to store audio track (16 bit so 2 bytes per short)
int audioLength = (int)(file.length()/2);
short[] audio = new short[audioLength];
try {
InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
int i = 0;
while (dis.available() > 0)
{ audio[i] =
dis.readShort(); i++;
}
// Close the input streams.
dis.close();
// Create and play a new
AudioTrack object
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequency,
channelConfiguration, audioEncoding, audioLength, AudioTrack.MODE_STREAM);
audioTrack.play();
audioTrack.write(audio, 0, audioLength);
} catch (Throwable t) {
Log.d(TAG, “An error occurred during playback”, t);
}
26
BipinRupadiya.com
USING THE CAMERA FOR
TAKING PICTURES
27
Using Intents to Take Pictures
The easiest way to take a picture from within your application is to fire
an Intent using the MediaStore.ACTION_IMAGE_CAPTURE action:
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
TAKE_PICTURE);
This launches a Camera application to take the photo, providing your
users with the full suite of camera functionality without you having to
rewrite the native Camera application.
Once users are satisfied with the image, the result is returned to
your application within the Intent received by the onActivityResult handler.
By default, the picture taken will be returned as a thumbnail, available
as a
raw bitmap within the data extra within the returned Intent.
To obtain a full image, you must specify a target file in which to store
it, encoded as a URI passed in using the MediaStore.EXTRA_OUTPUT extra
in the launch Intent
28
Requesting
a full-size picture using an Intent
File file = new File(Environment.getExternalStorageDirectory(),“test.jpg”); // Create an output file.
Uri outputFileUri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Generate the Intent.
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, TAKE_PICTURE); // Launch the camera app.
//Receiving pictures from an Intent
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE) {
// Check if the result includes a thumbnail Bitmap
if (data != null) {
if (data.hasExtra(“data”)) {
Bitmap thumbnail = data.getParcelableExtra(“data”);
imageView.setImageBitmap(thumbnail);
}
} else {
// If there is no thumbnail image data, the image will have been
stored in the target output URI.
// Resize the full image to fit in out image view. 29
Receiving pictures from an Intent (Conti..)
int width = imageView.getWidth();
int height = imageView.getHeight();
BitmapFactory.Options factoryOptions = new
BitmapFactory.Options(); factoryOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(outputFileUri.getPath(), factoryOptions);
int imageWidth = factoryOptions.outWidth;
int imageHeight =
factoryOptions.outHeight;
31
Using Intents to Record Video
To initiate video recording is use the MediaStore.ACTION_VIDEO_CAPTURE action Intent.
Starting a new Activity with this Intent launches the native video recorder, allowing users
to start, stop, review, and retake their video.
When they’re satisfied, a URI to the recorded video is provided to your Activity as the data
parameter of the returned Intent:
The video capture action Intent can contain the following three optional extras:
MediaStore.EXTRA_OUTPUT
By default, the video recorded by the video capture action will be stored in the default
Media Store.
If you want to record it elsewhere, you can specify an alternative URI using this extra.
MediaStore.EXTRA_VIDEO_QUALITY
There are currently two possible values:
0 for low (MMS) quality videos, or
1 for high (full resolution) videos. (default)
MediaStore.EXTRA_DURATION_LIMIT
The maximum length of the recorded video (in seconds).
32
BipinRupadiya.com
Recording video using an Intent
private static final int RECORD_VIDEO = 0;
private void startRecording() {
// Generate the Intent.
Intent intent = new
Intent(MediaStore.ACTION_VIDEO_CAPT
URE);
// Launch the camera app.
startActivityForResult(intent, RECORD_VIDEO);
}
@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (requestCode == RECORD_VIDEO) {
VideoView videoView = (VideoView)findViewById(R.id.videoView);
videoView.setVideoURI(data.getData());
videoView.start()
}
}
BipinRupadiya.com 33
Using
the Media Recorder to Record
Video
You can use the MediaRecorder class to record audio and/or video files
that can be used in your own applications or added to the Media Store.
To record any media in Android, your application needs the CAMERA
and RECORD_AUDIO and/or RECORD_VIDEO permissions as applicable:
<uses-permission android:name=”android.permission.RECORD_AUDIO”/>
<uses-permission android:name=”android.permission.RECORD_VIDEO”/>
<uses-permission android:name=”android.permission.CAMERA”/>
34
BipinRupadiya.com
Much like the Media Player, the Media Recorder manages recording as
a state machine.
This means that the order in which you configure and manage the
Media Recorder is important.
In the simplest terms, the transitions throughthe
state machine can be described as follows:
1. Create a new Media Recorder.
2. Unlock the Camera and assign it to the Media Recorder.
3. Specify the input sources to record from.
4. Select a profile to use for Android 2.2 and above, or define the
output format and specify the audio and video encoder, frame rate,
and output size.
5. Select an output file.
6. Assign a preview Surface.
7. Prepare the Media Recorder for recording.
8. Record.
9. End the recording.
35
BipinRupadiya.com
Preparing to record audio and video using the Media
Recorder
camera.unlock(); // Unlock the Camera to allow the Media Recorder to own it.
mediaRecorder.setCamera(camera); // Assign the Camera to the Media
// Configure the input sources.
Recorder.
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
; mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Set the recording profile.
CamcorderProfile profile = null;
if
(CamcorderProfile.hasProfile(Ca
mcorderProfile.QUALITY_1080P
))
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_1080P);
else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P))
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P))
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH))
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
if (profile != null)
mediaRecorder.setProfile(profile);
// Specify the output file
mediaRecorder.setOutputFile(“/sdcard/ 36
BipinRupadiya.com
myvideorecording.mp4”);
Previewing the Video Stream
When recording video, it’s considered good practice to display
a preview of the recorded video in real time.
Like the Camera preview, you can assign a Surface to display the
video stream using the setPreviewDisplay method on your
Media Recorder object.
mediaRecorder.setPreviewDisplay(holder.getSurface());
The live video preview stream will begin as soon as you make a
call
to prepare:
mediaRecorder.prepare();
37
Controlling the Recording
After configuring the Media Recorder and setting up the preview,
you can begin recording at any time by calling the start method:
mediaRecorder.start();
When you finish recording, call stop to end the playback, followed
by reset and release to free the Media Recorder resources,
mediaRecorder.stop();
// Reset and release the media recorder.
mediaRecorder.reset();
mediaRecorder.release();
camera.lock();
38
ADDING MEDIA TO THE MEDIA STORE
By default, media files created by your application that are stored
in private application folders will be unavailable to other applications.
To make them visible, you need to insert them into the Media Store.
Android provides two options for this.
The preferred approach is to use the
Media Scanner to interpret your file and insert
it automatically.
you can manually insert a new record in the appropriate Content
Provider.
Using the Media Scanner is almost always the better approach.
39
Inserting
Media Using the Media Scanner
MediaScannerConnection class provides the scanFile() as a simple way for you to add it to the
Media Store without needing to construct the full record for the Media Store Content Provider.