Android 4
24. Media - Part A
This chapter
Android's open platform provides API capable of playing and recording a wide range of image, audio, and video formats, both locally and streamed content under the android.media package.
The class android.media.MediaPlayer is the heart of the
android.media package. The content of the
android.media.MediaPlayer is coming from the sources such as:
- Web
- .apk file
We can play content that is packaged. Our media content can be packaged as a resource or as an asset. - SD card
The MediaPlayer can handle the following different formats:
- H.264 format, m4v container
- 3GPP format, 3gp container
- MPEG-4 format, mp4 container
- PCM/WAVE format, wav container
- (Note)mov files should be converted to one of the above formats.
Table from http://developer.android.com/guide/appendix/media-formats.html
We can add video files to an AVD by placing them on the AVD's SD card.
- Launch AVD using the Window > AVD Manager .
- Window > Open Perspective to open the DDMS perspective.
- In the DDMS perspective, select AVD in the Devices list.
- Select the File Explorer tab to display the AVD's files.
- Drag and drop video files to mnt/sdcard.
- Shutdown the AVD, and restart it with Launch from snapshot unchecked, which will enable AVD to scan the SD card for the new files.
In this example, we'll learn how to playback a video either from a web server or from a SD card.
Android provides a specialized view control, android.widget.VideoView that encapsulates creating and initializing the MediaPlayer.
Let's look at the our files
layout file, /res/main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android= "http://schemas.android.com/apk/res/android"> <VideoView android:id="@+id/videoView" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </LinearLayout>
manifest file:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package="com.bogotobogo.android.video" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Video" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="4" /> <uses-permission android:name="android.permission.INTERNET"> </uses-permission> </manifest>
and finally, our Java code, Video.java:
package com.bogotobogo.android.video; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.widget.MediaController; import android.widget.VideoView; public class Video extends Activity { /** Called when the activity is first created. */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.main); VideoView videoView = (VideoView)this.findViewById(R.id.videoView); MediaController mc = new MediaController(this); videoView.setMediaController(mc); // (1) Web //videoView.setVideoURI(Uri.parse( //"http://www.bogotobogo.com/Video/sample.3gp")); //"http://www.bogotobogo.com/Video/sample.mp4")); /* (2) SD card */ //videoView.setVideoPath("/sdcard/sample.3gp"); //videoView.setVideoPath("/sdcard/sample.mp4"); videoView.setVideoURI(Uri.parse( "file:///sdcard/sample.mp4")); videoView.requestFocus(); videoView.start(); } }
Here we have 2 video files:
sample.3gp and sample.mp4.
To play video, we need to create a VideoView widget and set that as the content of the UI.
this.setContentView(R.layout.main); VideoView videoView = (VideoView)this.findViewById(R.id.videoView);
When the application runs, we'll see the controls for about three seconds, and then they disappear. We get them back by clicking anywhere within the video frame.
All of the playback functionality is hidden behind the VideoView class. All we're doing here is feeding the video contents to the video player.
In this example, we're using a VideoView component to display the video content. However, instead of creating our own button controls, we create a MediaController that provides the buttons for us.
MediaController mc = new MediaController(this); videoView.setMediaController(mc);
Actually, calling setMediaController() enables several controls such as play, pause etc.
While
// (1) Web //videoView.setVideoURI(Uri.parse( //"http://www.bogotobogo.com/Video/sample.3gp")); //"http://www.bogotobogo.com/Video/sample.mp4")); /* (2) SD card */ //videoView.setVideoPath("/sdcard/sample.3gp"); //videoView.setVideoPath("/sdcard/sample.mp4"); videoView.setVideoURI(Uri.parse( "file:///sdcard/sample.mp4"));
Note that we need to set permission for the Web case use.
<uses-permission android:name="android.permission.INTERNET"> </uses-permission>
Files used in this VideoView example,
Video.zip
In the next section, we'll learn how to put the video files into the SD card.
SD cards are one of the sources of content for the MediaPlayer. They are used in Android phones for storing user data, usually media content such as pictures, audio, and video.
Let's bring up File Explorer.
Start the emulator and wait the emulator initializes. Then,
Window > Show View > Other.
Select File Explorer.
Then, click OK.
To push a file onto the SD card, select the sdcard folder in the File Explorer and choose the button with the right-facing arrow which is at the top-right corner. This launches a dialog box that lets you select a file. Select the file that we want to upload to the SD card.
We may get "Failed to push selection: Read-only file system", if we try to push files without highlighting sdcard folder in the File Explorer.
Now we have put all files into the SD card.
One more thing. The directory called DCIM is the Digital Camera Images directory. It's an industry standard to put a DCIM directory within the root directory of an SD card that's used for digital images.
If we are creating an application whose target is Android 1.6 or newer and we want to be able to write to the SD card, we need to add the permission to write:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"> </uses-permission>
Multimedia playback in Android is handled by the MediaPlayer class. We can play media stored in application resources, local files, Content Providers, or streamed from a network URI.
In this section, we need 3 video files and 1 audio file:
sample.3gp, sample.mp4, samplemp4.mp4, and sample.mp3,
Files used in section 24.3-5 example,
AudioVideo.zip
We will play audio and video files in three ways:
- Local: SD card.
path = "/sdcard/sample.mov"; mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path);
- Resources: /res/raw.
mMediaPlayer = MediaPlayer.create(this, R.raw.samplemp4); mMediaPlayer.start();
- Stream: web.
path = "http://www.bogotobogo.com/Video/sample.3gp"; mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(path);
As we can see from the Manifest file below, we added additional two activities beside the Main Activity: MyAudioPlayer and MyVideoPlayer.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.bogotobogo.android.audiovideo" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".AudioVideo" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MyAudioPlayer" android:label="AudioPlayer"> <intent-filter> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> <activity android:name=".MyVideoPlayer" android:label="VideoPlayer"> <intent-filter> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="4" /> </manifest>
Let's look at our launch code, AudioVideo.java:
package com.bogotobogo.android.audiovideo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class AudioVideo extends Activity { private Button mlocalvideo; private Button mresourcesvideo; private Button mstreamvideo; private Button mlocalaudio; private Button mresourcesaudio; private Button mstreamaudio; 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 static final int LOCAL_VIDEO = 4; private static final int STREAM_VIDEO = 5; private static final int RESOURCES_VIDEO = 6; @Override protected void onCreate(Bundle icicle) { // TODO Auto-generated method stub super.onCreate(icicle); setContentView(R.layout.mediaplayer_1); mlocalaudio = (Button) findViewById(R.id.localaudio); mlocalaudio.setOnClickListener(mLocalAudioListener); mresourcesaudio = (Button) findViewById(R.id.resourcesaudio); mresourcesaudio.setOnClickListener(mResourcesAudioListener); mstreamaudio = (Button) findViewById(R.id.streamaudio); mstreamaudio.setOnClickListener(mStreamAudioListener); mlocalvideo = (Button) findViewById(R.id.localvideo); mlocalvideo.setOnClickListener(mLocalVideoListener); mresourcesvideo = (Button) findViewById(R.id.resourcesvideo); mresourcesvideo.setOnClickListener(mResourcesVideoListener); mstreamvideo = (Button) findViewById(R.id.streamvideo); mstreamvideo.setOnClickListener(mStreamVideoListener); } private OnClickListener mLocalAudioListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this.getApplication(), MyAudioPlayer.class); intent.putExtra(AUDIOVIDEO, LOCAL_AUDIO); startActivity(intent); } }; private OnClickListener mResourcesAudioListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this.getApplication(), MyAudioPlayer.class); intent.putExtra(AUDIOVIDEO, RESOURCES_AUDIO); startActivity(intent); } }; private OnClickListener mStreamAudioListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this, MyAudioPlayer.class); intent.putExtra(AUDIOVIDEO, STREAM_AUDIO); startActivity(intent); } }; private OnClickListener mLocalVideoListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this, MyVideoPlayer.class); intent.putExtra(AUDIOVIDEO, LOCAL_VIDEO); startActivity(intent); } }; private OnClickListener mResourcesVideoListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this.getApplication(), MyVideoPlayer.class); intent.putExtra(AUDIOVIDEO, RESOURCES_VIDEO); startActivity(intent); } }; private OnClickListener mStreamVideoListener = new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this, MyVideoPlayer.class); intent.putExtra(AUDIOVIDEO, STREAM_VIDEO); startActivity(intent); } }; }
We set the view:
setContentView(R.layout.mediaplayer_1);
The user interface consists of a LinearLayout with y buttons: three for audio and the other three for video. The layout file /res/mediaplayer_1.xml is shown below:
<?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"> <Button android:id="@+id/localvideo" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/local_video"/> <Button android:id="@+id/resourcesvideo" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/res_video"/> <Button android:id="@+id/streamvideo" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/stream_video"/> <Button android:id="@+id/localaudio" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/local_audio"/> <Button android:id="@+id/resourcesaudio" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/res_audio"/> <Button android:id="@+id/streamaudio" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="@string/stream_audio"/> </LinearLayout>
Then we register for the on-click event by calling the setOnClickListener() method with an onClickListener. An anonymous listener is created on the fly to handle click events for each button.
mlocalaudio = (Button) findViewById(R.id.localaudio); mlocalaudio.setOnClickListener(mLocalAudioListener); .... private OnClickListener mLocalAudioListener = new OnClickListen() { public void onClick(View v) { Intent intent = new Intent(AudioVideo.this.getApplication(), MyAudioPlayer.class); intent.putExtra(AUDIOVIDEO, LOCAL_AUDIO); startActivity(intent); } };
In the onClick() method, to explicitly select an Activity class to start, we create a new intent, specifying the current application Context, AudioVideo.this.getApplication(), and Activity class, MyAudioPlayer.class, to launch. Then, pass this intent into startActivity().
After startActivity() is called, the new Activity (in this example MyAudioPlayer) will be created and become visible and active, moving to the top of the Activity stack.In addition to its primary attributes of action and data, an intent include additional attributes called extras.
intent.putExtra(AUDIOVIDEO, LOCAL_AUDIO);An extra can provide more information to the component that receives the intent. The extra data is in the form of key/value pairs: the key name should start with the package name, the value can be any fundamental data type or arbitrary object. In our example, we put a string for package
private static final String AUDIOVIDEO = "audiovideo";and an int for the type of play.
private static final int LOCAL_AUDIO = 1;
Next sections:
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization