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" /> |
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" /> |
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" /> |
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:text = "简单音乐播放器" android:textsize = "25sp" /> |
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:text = "录音" android:textsize = "30sp" ></ BUTTON > |
5 | < BUTTON android:id = "@+id/Button02" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "停止" android:textsize = "30sp" 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:label = "@string/app_name" android:configchanges = "orientation|keyboardHidden|keyboard" android:screenorientation = "portrait" android:name = ".MainActivity" > |
06 | < ACTION android:name = "android.intent.action.MAIN" /> |
07 | < CATEGORY android:name = "android.intent.category.LAUNCHER" /> |
12 | < USES android:minsdkversion = "4" -sdk /> |
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窗口直接抓取的,下图中右上角颜色最深的图标就是抓取真机截图的按钮: