登录 立即注册
安币:

安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户

查看: 1490775|回复: 115

第二十八讲:Android多媒体(Media)入门

  [复制链接]

0

主题

0

帖子

-16

安币

限制会员

发表于 2011-4-29 12:43:42 | 显示全部楼层 |阅读模式
本帖最后由 andbus 于 2011-4-29 12:53 编辑

本讲内容: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"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3.         <item android:drawable="@drawable/play_disable" android:state_enabled="false"> <!-- state_enabled=false -->
  4.         <item android:drawable="@drawable/play_50"> <!-- default -->
  5. </item></item></selector>
复制代码
pause.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3.         <item android:drawable="@drawable/pause_disable" android:state_enabled="false"> <!-- state_enabled=false -->
  4.         <item android:drawable="@drawable/pause_50"> <!-- default -->
  5. </item></item></selector>
复制代码
stop.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3.         <item android:drawable="@drawable/stop_disable" android:state_enabled="false"> <!-- state_enabled=false -->
  4.         <item android:drawable="@drawable/stop_50"> <!-- default -->
  5. </item></item></selector>
复制代码
3、res/layout/main.xml 的内容如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
  3.         <textview android:layout_width="fill_parent" android:layout_height="wrap_content" android:textsize="25sp" android:text="简单音乐播放器">
  4. </textview></linearlayout>
  5. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent">

  6.                 <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:adjustviewbounds="true" android:id="@+id/play" android:background="@drawable/play">
  7.                 </imagebutton>

  8.                 <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:adjustviewbounds="true" android:id="@+id/pause" android:background="@drawable/pause">
  9.                 </imagebutton>

  10.                 <imagebutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:adjustviewbounds="true" android:id="@+id/stop" android:background="@drawable/stop">
  11.                 </imagebutton>
  12.         </linearlayout>
复制代码
4、MainMusic.java的内容如下:

  1. package android.basic.lesson28;

  2. import java.io.IOException;

  3. import android.app.Activity;
  4. import android.media.MediaPlayer;
  5. import android.media.MediaPlayer.OnCompletionListener;
  6. import android.media.MediaPlayer.OnPreparedListener;
  7. import android.os.Bundle;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.ImageButton;
  11. import android.widget.Toast;

  12. public class MainMusic extends Activity {

  13.         // 声明变量
  14.         private ImageButton play, pause, stop;
  15.         private MediaPlayer mPlayer;

  16.         /** Called when the activity is first created. */
  17.         @Override
  18.         public void onCreate(Bundle savedInstanceState) {
  19.                 super.onCreate(savedInstanceState);
  20.                 setContentView(R.layout.main);

  21.                 // 定义UI组件
  22.                 play = (ImageButton) findViewById(R.id.play);
  23.                 pause = (ImageButton) findViewById(R.id.pause);
  24.                 stop = (ImageButton) findViewById(R.id.stop);

  25.                 // 按钮先全部失效
  26.                 play.setEnabled(false);
  27.                 pause.setEnabled(false);
  28.                 stop.setEnabled(false);

  29.                 // 定义单击监听器
  30.                 OnClickListener ocl = new View.OnClickListener() {

  31.                         @Override
  32.                         public void onClick(View v) {
  33.                                 switch (v.getId()) {
  34.                                 case R.id.play:
  35.                                         // 播放
  36.                                         Toast.makeText(MainMusic.this, "点击播放", Toast.LENGTH_SHORT)
  37.                                                         .show();
  38.                                         play();
  39.                                         break;
  40.                                 case R.id.pause:
  41.                                         // 暂停
  42.                                         Toast.makeText(MainMusic.this, "暂停播放", Toast.LENGTH_SHORT)
  43.                                                         .show();
  44.                                         pause();
  45.                                         break;
  46.                                 case R.id.stop:
  47.                                         // 停止
  48.                                         Toast.makeText(MainMusic.this, "停止播放", Toast.LENGTH_SHORT)
  49.                                                         .show();
  50.                                         stop();
  51.                                         break;
  52.                                 }
  53.                         }
  54.                 };

  55.                 // 绑定单击监听
  56.                 play.setOnClickListener(ocl);
  57.                 pause.setOnClickListener(ocl);
  58.                 stop.setOnClickListener(ocl);

  59.                 // 初始化
  60.                 initMediaPlayer();
  61.         }

  62.         // 初始化播放器
  63.         private void initMediaPlayer() {

  64.                 // 定义播放器
  65.                 mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.love);

  66.                 // 定义资源准备好的监听器
  67.                 mPlayer.setOnPreparedListener(new OnPreparedListener() {
  68.                         @Override
  69.                         public void onPrepared(MediaPlayer mp) {
  70.                                 // 资源准备好了再让播放器按钮有效
  71.                                 Toast.makeText(MainMusic.this, "onPrepared", Toast.LENGTH_SHORT)
  72.                                                 .show();
  73.                                 play.setEnabled(true);
  74.                         }
  75.                 });

  76.                 // 定义播放完成监听器
  77.                 mPlayer.setOnCompletionListener(new OnCompletionListener() {

  78.                         @Override
  79.                         public void onCompletion(MediaPlayer mp) {
  80.                                 Toast.makeText(MainMusic.this, "onCompletion",
  81.                                                 Toast.LENGTH_SHORT).show();
  82.                                 stop();
  83.                         }
  84.                 });
  85.         }

  86.         // 停止播放
  87.         private void stop() {
  88.                 mPlayer.stop();
  89.                 pause.setEnabled(false);
  90.                 stop.setEnabled(false);
  91.                 try {
  92.                         mPlayer.prepare();
  93.                         mPlayer.seekTo(0);
  94.                         play.setEnabled(true);
  95.                 } catch (IllegalStateException e) {
  96.                         e.printStackTrace();
  97.                 } catch (IOException e) {
  98.                         e.printStackTrace();
  99.                 }

  100.         }

  101.         // 播放
  102.         private void play() {

  103.                 mPlayer.start();
  104.                 play.setEnabled(false);
  105.                 pause.setEnabled(true);
  106.                 stop.setEnabled(true);
  107.         }

  108.         // 暂停
  109.         private void pause() {
  110.                 mPlayer.pause();
  111.                 play.setEnabled(true);
  112.                 pause.setEnabled(false);
  113.                 stop.setEnabled(true);
  114.         }

  115.         // Activity销毁前停止播放
  116.         @Override
  117.         protected void onDestroy() {
  118.                 super.onDestroy();
  119.                 if (stop.isEnabled()) {
  120.                         stop();
  121.                 }

  122.         }

  123. }
复制代码

5、运行程序,查看效果[/url][url=http://android.yaohuiji.com/wp-content/uploads/2010/08/image31.png]
二、简单视频播放器Android为视频播放提供了VideoView 和 MediaController 两个现成的组件,让我们可以方便的实现MP4、3GP等视频的播放。下面我们通过一个例子来看一下:1、新建一个项目 Lesson28_Video2、使用 Format Factory 这个软件压缩一个视频备用,我这里压缩的参数如下:
[/url]
注意,如果播放时完全无法播放或者只有声音没有图像,你就需要换压缩软件和调整压缩参数重新压缩视频了,暂时只能这样,我也是折腾了2-3小时都是黑屏,郁闷中(似乎得出一个答案,是否黑屏和机器设备的性能有关,我降低压缩分辨率和每秒帧数,出图像音画同步,如果提高每秒帧数,声音出来后十几秒图像才会出来,但是出来后音画还是同步的,有兴趣的朋友可以多测试测试给出一个结论)。用命令行的方式拷贝此视频到存储卡(sdcard)中,为什么不用eclipse中的可视化工具拷贝呢?因为那个方式靠大文件的时候经常失败,而命令行方式我没拷贝失败一次过。命令就是 adb push ,具体截个图给你看:

[url=http://android.yaohuiji.com/wp-content/uploads/2010/08/image33.png]

3、res\layout\main.xml的内容如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top">
  3. <videoview android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/VideoView01">
  4. </videoview>
  5. </linearlayout>
复制代码

4、MainVideo.java的内容如下:
  1. package android.basic.lesson28;

  2. import android.app.Activity;
  3. import android.net.Uri;
  4. import android.os.Bundle;
  5. import android.view.Window;
  6. import android.view.WindowManager;
  7. import android.widget.MediaController;
  8. import android.widget.VideoView;

  9. public class MainVideo extends Activity {
  10.         /** Called when the activity is first created. */
  11.         @Override
  12.         public void onCreate(Bundle savedInstanceState) {
  13.                 super.onCreate(savedInstanceState);
  14.                 //全屏
  15.                 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  16.                 //标题去掉
  17.                 this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  18.                 //要在全屏等设置完毕后再加载布局
  19.                 setContentView(R.layout.main);

  20.                 //定义UI组件
  21.                 VideoView videoView = (VideoView) findViewById(R.id.VideoView01);
  22.                 //定义MediaController对象
  23.                 MediaController mediaController = new MediaController(this);
  24.                 //把MediaController对象绑定到VideoView上
  25.                 mediaController.setAnchorView(videoView);
  26.                 //设置VideoView的控制器是mediaController
  27.                 videoView.setMediaController(mediaController);

  28.                 //这两种方法都可以 videoView.setVideoPath("file:///sdcard/love_480320.mp4");
  29.                 videoView.setVideoURI(Uri.parse("/sdcard/love_480320.mp4"));
  30.                 //启动后就播放
  31.                 videoView.start();
  32.         }
  33. }
复制代码

5、运行效果如下:
[/url][url=http://android.yaohuiji.com/wp-content/uploads/2010/08/image35.png]

三、简单录音程序1、新建一个一个项目 Tip_Recorder,主activity名字是  MainActivity2、其布局文件main.xml的代码是:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center">

  3.         <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="30sp" android:text="录音" android:id="@+id/Button01"></button>
  4.         <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="30sp" android:text="停止" android:id="@+id/Button02" android:layout_margintop="20dp"></button>
  5. </linearlayout>
复制代码
3、主程序文件 MainActivity.java的代码如下:

  1. package android.tip.yaoyao;

  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.Calendar;
  5. import java.util.Locale;

  6. import android.app.Activity;
  7. import android.media.MediaRecorder;
  8. import android.os.Bundle;
  9. import android.text.format.DateFormat;
  10. import android.view.View;
  11. import android.widget.Button;
  12. import android.widget.Toast;

  13. public class MainActivity extends Activity {

  14.         private Button recordButton;
  15.         private Button stopButton;

  16.         private MediaRecorder mr;

  17.         @Override
  18.         public void onCreate(Bundle savedInstanceState) {
  19.                 super.onCreate(savedInstanceState);
  20.                 setContentView(R.layout.main);

  21.                 recordButton = (Button) this.findViewById(R.id.Button01);
  22.                 stopButton = (Button) this.findViewById(R.id.Button02);

  23.                 // 录音按钮点击事件
  24.                 recordButton.setOnClickListener(new View.OnClickListener() {

  25.                         @Override
  26.                         public void onClick(View v) {

  27.                                 File file = new File("/sdcard/"
  28.                                                 + "YY"
  29.                                                 + new DateFormat().format("yyyyMMdd_hhmmss",
  30.                                                                 Calendar.getInstance(Locale.CHINA)) + ".amr");

  31.                                 Toast.makeText(getApplicationContext(), "正在录音,录音文件在"+file.getAbsolutePath(), Toast.LENGTH_LONG)
  32.                                                 .show();

  33.                                 // 创建录音对象
  34.                                 mr = new MediaRecorder();

  35.                                 // 从麦克风源进行录音
  36.                                 mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT);

  37.                                 // 设置输出格式
  38.                                 mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);

  39.                                 // 设置编码格式
  40.                                 mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

  41.                                 // 设置输出文件
  42.                                 mr.setOutputFile(file.getAbsolutePath());

  43.                                 try {
  44.                                         // 创建文件
  45.                                         file.createNewFile();
  46.                                         // 准备录制
  47.                                         mr.prepare();
  48.                                 } catch (IllegalStateException e) {
  49.                                         e.printStackTrace();
  50.                                 } catch (IOException e) {
  51.                                         e.printStackTrace();
  52.                                 }
  53.                                 // 开始录制
  54.                                 mr.start();
  55.                                 recordButton.setText("录音中……");
  56.                         }
  57.                 });

  58.                 // 停止按钮点击事件
  59.                 stopButton.setOnClickListener(new View.OnClickListener() {

  60.                         @Override
  61.                         public void onClick(View v) {

  62.                                 if (mr != null) {
  63.                                         mr.stop();
  64.                                         mr.release();
  65.                                         mr = null;
  66.                                         recordButton.setText("录音");
  67.                                         Toast.makeText(getApplicationContext(), "录音完毕", Toast.LENGTH_LONG).show();
  68.                                 }
  69.                         }
  70.                 });

  71.         }

  72. }
复制代码
4、因为录音和写存储卡都需要权限声明,所以这里也把AndroidManifest.xml代码提供出来:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionname="1.0" android:versioncode="1" package="android.tip.yaoyao">
  3.     <application android:debuggable="true" android:label="@string/app_name" android:icon="@drawable/icon">
  4.         <activity android:label="@string/app_name" android:configchanges="orientation|keyboardHidden|keyboard" android:screenorientation="portrait" android:name=".MainActivity">
  5.             <intent -filter="">
  6.                 <action android:name="android.intent.action.MAIN">
  7.                 <category android:name="android.intent.category.LAUNCHER">
  8.             </category></action></intent>
  9.         </activity>

  10.     </application>
  11.     <uses -sdk="" android:minsdkversion="4">

  12. <uses -permission="" android:name="android.permission.RECORD_AUDIO"></uses>
  13. <uses -permission="" android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses>
  14. </uses></manifest>
复制代码
5、编译并运行程序,查看结果。
[/url]
点击录音:
[url=http://android.yaohuiji.com/wp-content/uploads/2010/11/image8.png]

录音文件在存储卡的根目录几个以YY开头的amr文件
[/url]

6、这个例子要用到录音设备,而模拟器并不能把电脑声卡模拟出来使用,因此这个例子必须在真机上进行测试。 真机上测试方法也很简单。
  • 在真机上把USB调试模式打开,
  • 把真机用USB线与电脑连接
  • 设置电脑和手机的连接方式为 ”仅充电“(此时手机可以操作存储卡)
  • 打开Eclipse,在不选择模拟器的情况下运行程序,此时,Eclipse会自动找到真机,并使用它运行程序,最完美的是他可以把真机运行程序的输出信息,照样输出在Eclipse中的Logcat日志中。

上面的真机截图也是通过Eclipse的DDMS窗口直接抓取的,下图中右上角颜色最深的图标就是抓取真机截图的按钮:

[url=http://android.yaohuiji.com/wp-content/uploads/2010/11/43af369025cd.jpg]


好了本讲内容就到这里,下次再见。







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

1

主题

182

帖子

73

安币

程序猿

Rank: 2

发表于 2011-9-22 13:39:31 | 显示全部楼层
很好, 谢谢分享

0

主题

47

帖子

35

安币

程序猿

Rank: 2

发表于 2011-10-24 23:28:00 | 显示全部楼层
很好, 谢谢分享

0

主题

83

帖子

206

安币

攻城狮

Rank: 3Rank: 3

发表于 2012-3-1 14:30:11 | 显示全部楼层
谢谢分享!!!

1

主题

78

帖子

87

安币

程序猿

Rank: 2

发表于 2012-3-19 21:05:49 | 显示全部楼层
谢谢分享!!!!!

98

主题

1076

帖子

4130

安币

码皇(巴士元老)

Android奋斗者

Rank: 8Rank: 8

QQ达人

QQ
发表于 2012-3-23 23:47:24 | 显示全部楼层
真的不错哦
加油!!

0

主题

47

帖子

360

安币

攻城狮

Rank: 3Rank: 3

QQ达人

发表于 2012-3-24 17:32:02 | 显示全部楼层
为什么我在做 一个简单播放器——main.xml的时候,在第二个<linearlayout>提示错误:The markup in the document following the root element must be well-formed. 这个是哪里出错了啊?

0

主题

28

帖子

77

安币

初级码农

Rank: 1

QQ达人

发表于 2012-3-25 19:25:01 | 显示全部楼层
{:soso_e179:}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区
联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 广东互联网违法和不良信息举报中心|中国互联网举报中心|下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表