本讲内容:Android中的音频和视频使用入门指南
Android 提供了 MediaPlayer 和 MediaRecorder 两个工具类,来帮助开发者操作音频和视频。我们通过两个小例子来学习一下多媒体资源的使用。
一、 简单音乐播放器
1、新建一个项目Lesson28_Music , 主Activity的名字是 MainMusic.java
2、拷贝
这几张图片到res/drawable目录下,并建立3个xml文件,拷贝love.mp3到res/raw文件中。
play.xml
1 |
<?xml version="1.0" encoding="utf-8"?>
|
3 |
<item android:state_enabled="false" android:drawable="@drawable/play_disable">
|
4 |
<item android:drawable="@drawable/play_50">
|
5 |
</item></item></selector>
|
pause.xml
1 |
<?xml version="1.0" encoding="utf-8"?>
|
3 |
<item android:state_enabled="false" android:drawable="@drawable/pause_disable">
|
4 |
<item android:drawable="@drawable/pause_50">
|
5 |
</item></item></selector>
|
stop.xml
1 |
<?xml version="1.0" encoding="utf-8"?>
|
3 |
<item android:state_enabled="false" android:drawable="@drawable/stop_disable">
|
4 |
<item android:drawable="@drawable/stop_50">
|
5 |
</item></item></selector>
|
3、res/layout/main.xml 的内容如下:
01 |
<?xml version="1.0" encoding="utf-8"?>
|
03 |
<textview android:layout_width="fill_parent" android:layout_height="wrap_content" android:textsize="25sp" android:text="简单音乐播放器">
|
04 |
</textview></linearlayout>
|
07 |
<imagebutton android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/play" android:adjustviewbounds="true" android:layout_margin="4dp">
|
10 |
<imagebutton android:id="@+id/pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/pause" android:adjustviewbounds="true" android:layout_margin="4dp">
|
13 |
<imagebutton android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/stop" android:adjustviewbounds="true" android:layout_margin="4dp">
|
4、MainMusic.java的内容如下:
001 |
package android.basic.lesson28;
|
003 |
import java.io.IOException;
|
005 |
import android.app.Activity;
|
006 |
import android.media.MediaPlayer;
|
007 |
import android.media.MediaPlayer.OnCompletionListener;
|
008 |
import android.media.MediaPlayer.OnPreparedListener;
|
009 |
import android.os.Bundle;
|
010 |
import android.view.View;
|
011 |
import android.view.View.OnClickListener;
|
012 |
import android.widget.ImageButton;
|
013 |
import android.widget.Toast;
|
015 |
public class MainMusic extends Activity {
|
018 |
private ImageButton play, pause, stop;
|
019 |
private MediaPlayer mPlayer;
|
021 |
/** Called when the activity is first created. */
|
023 |
public void onCreate(Bundle savedInstanceState) {
|
024 |
super.onCreate(savedInstanceState);
|
025 |
setContentView(R.layout.main);
|
028 |
play = (ImageButton) findViewById(R.id.play);
|
029 |
pause = (ImageButton) findViewById(R.id.pause);
|
030 |
stop = (ImageButton) findViewById(R.id.stop);
|
033 |
play.setEnabled(false);
|
034 |
pause.setEnabled(false);
|
035 |
stop.setEnabled(false);
|
038 |
OnClickListener ocl = new View.OnClickListener() {
|
041 |
public void onClick(View v) {
|
045 |
Toast.makeText(MainMusic.this, "点击播放", Toast.LENGTH_SHORT)
|
051 |
Toast.makeText(MainMusic.this, "暂停播放", Toast.LENGTH_SHORT)
|
057 |
Toast.makeText(MainMusic.this, "停止播放", Toast.LENGTH_SHORT)
|
066 |
play.setOnClickListener(ocl);
|
067 |
pause.setOnClickListener(ocl);
|
068 |
stop.setOnClickListener(ocl);
|
075 |
private void initMediaPlayer() {
|
078 |
mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.love);
|
081 |
mPlayer.setOnPreparedListener(new OnPreparedListener() {
|
083 |
public void onPrepared(MediaPlayer mp) {
|
085 |
Toast.makeText(MainMusic.this, "onPrepared", Toast.LENGTH_SHORT)
|
087 |
play.setEnabled(true);
|
092 |
mPlayer.setOnCompletionListener(new OnCompletionListener() {
|
095 |
public void onCompletion(MediaPlayer mp) {
|
096 |
Toast.makeText(MainMusic.this, "onCompletion",
|
097 |
Toast.LENGTH_SHORT).show();
|
104 |
private void stop() {
|
106 |
pause.setEnabled(false);
|
107 |
stop.setEnabled(false);
|
111 |
play.setEnabled(true);
|
112 |
} catch (IllegalStateException e) {
|
114 |
} catch (IOException e) {
|
121 |
private void play() {
|
124 |
play.setEnabled(false);
|
125 |
pause.setEnabled(true);
|
126 |
stop.setEnabled(true);
|
130 |
private void pause() {
|
132 |
play.setEnabled(true);
|
133 |
pause.setEnabled(false);
|
134 |
stop.setEnabled(true);
|
139 |
protected void onDestroy() {
|
141 |
if (stop.isEnabled()) {
|
5、运行程序,查看效果


二、简单视频播放器
Android为视频播放提供了VideoView 和 MediaController 两个现成的组件,让我们可以方便的实现MP4、3GP等视频的播放。下面我们通过一个例子来看一下:
1、新建一个项目 Lesson28_Video
2、使用 Format Factory 这个软件压缩一个视频备用,我这里压缩的参数如下:

注意,如果播放时完全无法播放或者只有声音没有图像,你就需要换压缩软件和调整压缩参数重新压缩视频了,暂时只能这样,我也是折腾了2-3小时都是黑屏,郁闷中(似乎得出一个答案,是否黑屏和机器设备的性能有关,我降低压缩分辨率和每秒帧数,出图像音画同步,如果提高每秒帧数,声音出来后十几秒图像才会出来,但是出来后音画还是同步的,有兴趣的朋友可以多测试测试给出一个结论)。
用命令行的方式拷贝此视频到存储卡(sdcard)中,为什么不用eclipse中的可视化工具拷贝呢?因为那个方式靠大文件的时候经常失败,而命令行方式我没拷贝失败一次过。命令就是 adb push ,具体截个图给你看:

3、res\layout\main.xml的内容如下:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
3 |
<videoview android:id="@+id/VideoView01" android:layout_width="fill_parent" android:layout_height="fill_parent">
|
4、MainVideo.java的内容如下:
01 |
package android.basic.lesson28;
|
03 |
import android.app.Activity;
|
04 |
import android.net.Uri;
|
05 |
import android.os.Bundle;
|
06 |
import android.view.Window;
|
07 |
import android.view.WindowManager;
|
08 |
import android.widget.MediaController;
|
09 |
import android.widget.VideoView;
|
11 |
public class MainVideo extends Activity {
|
12 |
/** Called when the activity is first created. */
|
14 |
public void onCreate(Bundle savedInstanceState) {
|
15 |
super.onCreate(savedInstanceState);
|
17 |
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
19 |
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
21 |
setContentView(R.layout.main);
|
24 |
VideoView videoView = (VideoView) findViewById(R.id.VideoView01);
|
26 |
MediaController mediaController = new MediaController(this);
|
28 |
mediaController.setAnchorView(videoView);
|
30 |
videoView.setMediaController(mediaController);
|
33 |
videoView.setVideoURI(Uri.parse("/sdcard/love_480320.mp4"));
|
5、运行效果如下:


三、简单录音程序
1、新建一个一个项目 Tip_Recorder,主activity名字是 MainActivity
2、其布局文件main.xml的代码是:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
4 |
<button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="30sp" android:text="录音"></button>
|
5 |
<button android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="30sp" android:text="停止" android:layout_marginTop="20dp"></button>
|
3、主程序文件 MainActivity.java的代码如下:
01 |
package android.tip.yaoyao;
|
04 |
import java.io.IOException;
|
05 |
import java.util.Calendar;
|
06 |
import java.util.Locale;
|
08 |
import android.app.Activity;
|
09 |
import android.media.MediaRecorder;
|
10 |
import android.os.Bundle;
|
11 |
import android.text.format.DateFormat;
|
12 |
import android.view.View;
|
13 |
import android.widget.Button;
|
14 |
import android.widget.Toast;
|
16 |
public class MainActivity extends Activity {
|
18 |
private Button recordButton;
|
19 |
private Button stopButton;
|
21 |
private MediaRecorder mr;
|
24 |
public void onCreate(Bundle savedInstanceState) {
|
25 |
super.onCreate(savedInstanceState);
|
26 |
setContentView(R.layout.main);
|
28 |
recordButton = (Button) this.findViewById(R.id.Button01);
|
29 |
stopButton = (Button) this.findViewById(R.id.Button02);
|
32 |
recordButton.setOnClickListener(new View.OnClickListener() {
|
35 |
public void onClick(View v) {
|
37 |
File file = new File("/sdcard/"
|
39 |
+ new DateFormat().format("yyyyMMdd_hhmmss",
|
40 |
Calendar.getInstance(Locale.CHINA)) + ".amr");
|
42 |
Toast.makeText(getApplicationContext(), "正在录音,录音文件在"+file.getAbsolutePath(), Toast.LENGTH_LONG)
|
46 |
mr = new MediaRecorder();
|
49 |
mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
|
52 |
mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
|
55 |
mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
|
58 |
mr.setOutputFile(file.getAbsolutePath());
|
65 |
} catch (IllegalStateException e) {
|
67 |
} catch (IOException e) {
|
72 |
recordButton.setText("录音中……");
|
77 |
stopButton.setOnClickListener(new View.OnClickListener() {
|
80 |
public void onClick(View v) {
|
86 |
recordButton.setText("录音");
|
87 |
Toast.makeText(getApplicationContext(), "录音完毕", Toast.LENGTH_LONG).show();
|
4、因为录音和写存储卡都需要权限声明,所以这里也把AndroidManifest.xml代码提供出来:
01 |
<?xml version="1.0" encoding="utf-8"?>
|
03 |
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
|
04 |
<activity android:name=".MainActivity" android:label="@string/app_name" android:screenorientation="portrait" android:configchanges="orientation|keyboardHidden|keyboard">
|
06 |
<action android:name="android.intent.action.MAIN">
|
07 |
<category android:name="android.intent.category.LAUNCHER">
|
08 |
</category></action></intent>
|
12 |
<uses -sdk="" android:minsdkversion="4">
|
14 |
<uses android:name="android.permission.RECORD_AUDIO" -permission=""></uses>
|
15 |
<uses android:name="android.permission.WRITE_EXTERNAL_STORAGE" -permission=""></uses>
|
5、编译并运行程序,查看结果。

点击录音:
录音文件在存储卡的根目录几个以YY开头的amr文件

6、这个例子要用到录音设备,而模拟器并不能把电脑声卡模拟出来使用,因此这个例子必须在真机上进行测试。 真机上测试方法也很简单。
- 在真机上把USB调试模式打开,
- 把真机用USB线与电脑连接
- 设置电脑和手机的连接方式为 ”仅充电“(此时手机可以操作存储卡)
- 打开Eclipse,在不选择模拟器的情况下运行程序,此时,Eclipse会自动找到真机,并使用它运行程序,最完美的是他可以把真机运行程序的输出信息,照样输出在Eclipse中的Logcat日志中。
上面的真机截图也是通过Eclipse的DDMS窗口直接抓取的,下图中右上角颜色最深的图标就是抓取真机截图的按钮:
好了本讲内容就到这里,下次再见。
转自 http://android.yaohuiji.com/archives/732