Android开发之Mediaplayer

 Android提供了常见的音频、视频的编码、解码机制。借助于多媒体类MediaPlayer的支持,开发者能够非常方便在在应用中播放音频、视频。本篇博客主要解说在Android平台下怎样播放一个音频文件。

  本篇博客主要内容例如以下:

MediaPlayer

  上面提到过,Android下对于音频、视频的支持均须要使用到MediaPlayer,它主要用来控制Android下播放文件或流的类。MediaPlayer处于Android多媒体包下"android.media.MediaPlayer",仅有一个无參的构造函数,尽管仅为我们提供了一个无參的构造函数,为了方便我们初始化,还为我们提供了几个静态的create()方法用于完毕MediaPlayer初始化的工作。

  • static MediaPlayer create(Context context,int resid):通过音频资源的Id来创建一个MediaPlayer实例。
  • static MediaPlayer create(Context context,Uri uri):通过一个音频资源的Uri地址来创建一个MediaPlayer实例。

  MediaPlayer除了通过上面两个create()方法在初始化的时候指定媒体资源,还能够通过MediaPlayer.setDataSource()方法为初始化后的MediaPlayer设置媒体资源,setDataSource()具有多个重载函数,适用于不同的媒体资源来源,下面解说几个经常使用的,其它的能够查阅官方文档。

  • void setDataSource(String path):通过一个媒体资源的地址指定MediaPlayer的数据源,这里的path能够是一个本地路径,也能够是网络路径。
  • void setDataSource(Context context,Uri uri):通过一个Uri指定MediaPlayer的数据源,这里的Uri能够是网络路径或这一个内容提供者的Uri。
  • void setDataSource(FileDescriptor fd):通过一个FileDescriptor指定一个MediaPlayer的数据源。

MediaPlayer的音频源

  通过上面介绍的初始化MediaPlayer的播放时媒体数据源的方法能够看出,MediaPlayer支持的数据源有:本地文件、内部的Uri(内容提供者)、外部Uri。

  如,设置一个本地SD卡的资源:

1                 mediaPlayer = new MediaPlayer();
2                 mediaPlayer.setDataSource("/sdcarc/a.mp3");

  注意读内存卡,还须要设定訪问内存卡的权限:

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

  如,设置一个外部uri的网络流媒体资源:

1                 mediaPlayer = new MediaPlayer();
2                 mediaPlayer.setDataSource(http://192.168.1.102:1231/music/a.mp3);

  假设訪问网络流媒体资源,还须要设置訪问网络的权限:

    <uses-permission android:name="android.permission.INTERNET"/>

使用MediaPlayer播放音乐

  MediaPlayer事实上是一个封装的非常好的音频、视频流媒体操作类,假设查看其源代码,会发现其内部是调用的native方法,所以它事实上是有C++实现的。

  既然是一个流媒体操作类,那么必定涉及到,播放、暂停、停止等操作,实际上MediaPlayer也为我们提供了对应的方法来直接操作流媒体。

  • void start():開始或恢复播放。
  • void stop():停止播放。
  • void pause():暂停播放。  

  通过上面三个方法,仅仅要设定好流媒体数据源,就可以在应用中播放流媒体资源,为了更好的操作流媒体,MediaPlayer还为我们提供了一些其它的方法,这里列出一些经常使用的,具体内容參阅官方文档。

  • int getDuration():获取流媒体的总播放时长,单位是毫秒。
  • int getCurrentPosition():获取当前流媒体的播放的位置,单位是毫秒。
  • void seekTo(int msec):设置当前MediaPlayer的播放位置,单位是毫秒。
  • void setLooping(boolean looping):设置是否循环播放。
  • boolean isLooping():推断是否循环播放。
  • boolean  isPlaying():推断是否正在播放。
  • void prepare():同步的方式装载流媒体文件。
  • void prepareAsync():异步的方式装载流媒体文件。
  • void release ():回收流媒体资源。
  • void setAudioStreamType(int streamtype):设置播放流媒体类型。
  • void setWakeMode(Context context, int mode):设置CPU唤醒的状态。
  • setNextMediaPlayer(MediaPlayer next):设置当前流媒体播放完成,下一个播放的MediaPlayer。

  大部分方法的看方法名就能够理解,可是有几个方法须要单独说明一下。

  在使用MediaPlayer播放一段流媒体的时候,须要使用prepare()或prepareAsync()方法把流媒体装载进MediaPlayer,才干够调用start()方法播放流媒体。                 

  setAudioStreamType()方法用于指定播放流媒体的类型,它传递的是一个int类型的数据,均以常量定义在AudioManager类中, 一般我们播放音频文件,设置为AudioManager.STREAM_MUSIC就可以。

  

  除了上面介绍的一些方法外,MediaPlayer还提供了一些事件的回调函数,这里介绍几个经常使用的:

  • setOnCompletionListener(MediaPlayer.OnCompletionListener listener):当流媒体播放完成的时候回调。
  • setOnErrorListener(MediaPlayer.OnErrorListener listener):当播放中错误发生的时候回调。
  • setOnPreparedListener(MediaPlayer.OnPreparedListener listener):当装载流媒体完成的时候回调。
  • setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):当使用seekTo()设置播放位置的时候回调。

MediaPlayer使用技巧

  在使用MediaPlayer的使用过程中,有个小技巧须要说明一下:

  1、在使用start()播放流媒体之前,须要装载流媒体资源。这里最好使用prepareAsync()用异步的方式装载流媒体资源。由于流媒体资源的装载是会消耗系统资源的,在一些硬件不理想的设备上,假设使用prepare()同步的方式装载资源,可能会造成UI界面的卡顿,这是很影响用于体验的。由于推荐使用异步装载的方式,为了避免还没有装载完毕就调用start()而报错的问题,须要绑定MediaPlayer.setOnPreparedListener()事件,它将在异步装载完毕之后回调。异步装载另一个优点就是避免装载超时引发ANR((Application
Not Responding)错误。

 1                 mediaPlayer = new MediaPlayer();
 2                 mediaPlayer.setDataSource(path);
 3                 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 4
 5                 // 通过异步的方式装载媒体资源
 6                 mediaPlayer.prepareAsync();
 7                 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
 8                     @Override
 9                     public void onPrepared(MediaPlayer mp) {
10                         // 装载完成回调
11                         mediaPlayer.start();
12                     }
13                 });                

  2、使用完MediaPlayer须要回收资源。MediaPlayer是非常消耗系统资源的,所以在使用完MediaPlayer,不要等待系统自己主动回收,最好是主动回收资源。

1         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
2             mediaPlayer.stop();
3             mediaPlayer.release();
4             mediaPlayer = null;
5         }

  3、使用MediaPlayer最好使用一个Service来使用,而且在Service的onDestory()方法中回收MediaPlayer资源,实际上,就算是直接使用Activity承载MediaPlayer,也最好在销毁的时候推断一下MediaPlayer是否被回收,假设未被回收,回收其资源,由于底层调用的native方法,假设不销毁还是会在底层继续播放,而承载的组件已经被销毁了,这个时候就无法获取到这个MediaPlayer进而控制它。

1     @Override
2     protected void onDestroy() {
3         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
4             mediaPlayer.stop();
5             mediaPlayer.release();
6             mediaPlayer = null;
7         }
8         super.onDestroy();
9     }

  4、对于单曲循环之类的操作,除了能够使用setLooping()方法进行设置之外,还能够为MediaPlayer注冊回调函数,MediaPlayer.setOnCompletionListener(),它会在MediaPlayer播放完成被回调。

 1                 // 设置循环播放
 2 //                mediaPlayer.setLooping(true);
 3                 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
 4
 5                     @Override
 6                     public void onCompletion(MediaPlayer mp) {
 7                         // 在播放完成被回调
 8                         play();
 9                     }
10                 });

  5、由于MediaPlayer一直操作的是一个流媒体,所以无可避免的可能一段流媒体资源,前半段能够正常播放,而中间一段由于解析或者源文件错误等问题,造成中间一段无法播放问题,须要我们处理这个错误,否则会影响Ux(用户体验)。能够为MediaPlayer注冊回调函数setOnErrorListener()来设置出错之后的解决的方法,一般又一次播放或者播放下一个流媒体就可以。  

1                 mediaPlayer.setOnErrorListener(new OnErrorListener() {
2
3                     @Override
4                     public boolean onError(MediaPlayer mp, int what, int extra) {
5                         play();
6                         return false;
7                     }
8                 });

Demo--一个简单的MP3播放器

  上面已经介绍了MediaPlayer播放一段音频文件的全部须要用到的内容。以下通过一个简单的Demo来演示怎样使用MediaPlayer播放一个SD卡上的MP3文件。操作MediaPlayer应该放在Service中完毕,这里为了简单,使用Activity直接操作MediaPlayer。代码凝视里写的非常清楚里,这里不再累述。

  运行这个演示样例须要在/sdcard/文件夹下存在xm.mp3的文件。  

  1 package cn.bgxt.mediaplayerdemo;
  2
  3 import java.io.File;
  4 import android.media.AudioManager;
  5 import android.media.MediaPlayer;
  6 import android.media.MediaPlayer.OnCompletionListener;
  7 import android.media.MediaPlayer.OnErrorListener;
  8 import android.media.MediaPlayer.OnPreparedListener;
  9 import android.os.Bundle;
 10 import android.app.Activity;
 11 import android.view.View;
 12 import android.widget.Button;
 13 import android.widget.EditText;
 14 import android.widget.Toast;
 15
 16 public class MainActivity extends Activity {
 17     private EditText et_path;
 18     private Button btn_play, btn_pause, btn_replay, btn_stop;
 19     private MediaPlayer mediaPlayer;
 20
 21     @Override
 22     protected void onCreate(Bundle savedInstanceState) {
 23         super.onCreate(savedInstanceState);
 24         setContentView(R.layout.activity_main);
 25
 26         et_path = (EditText) findViewById(R.id.et_path);
 27         btn_play = (Button) findViewById(R.id.btn_play);
 28         btn_pause = (Button) findViewById(R.id.btn_pause);
 29         btn_replay = (Button) findViewById(R.id.btn_replay);
 30         btn_stop = (Button) findViewById(R.id.btn_stop);
 31
 32         btn_play.setOnClickListener(click);
 33         btn_pause.setOnClickListener(click);
 34         btn_replay.setOnClickListener(click);
 35         btn_stop.setOnClickListener(click);
 36     }
 37
 38     private View.OnClickListener click = new View.OnClickListener() {
 39
 40         @Override
 41         public void onClick(View v) {
 42
 43             switch (v.getId()) {
 44             case R.id.btn_play:
 45                 play();
 46                 break;
 47             case R.id.btn_pause:
 48                 pause();
 49                 break;
 50             case R.id.btn_replay:
 51                 replay();
 52                 break;
 53             case R.id.btn_stop:
 54                 stop();
 55                 break;
 56             default:
 57                 break;
 58             }
 59         }
 60     };
 61     /**
 62      * 播放音乐
 63      */
 64     protected void play() {
 65         String path = et_path.getText().toString().trim();
 66         File file = new File(path);
 67         if (file.exists() && file.length() > 0) {
 68             try {
 69                 mediaPlayer = new MediaPlayer();
 70                 // 设置指定的流媒体地址
 71                 mediaPlayer.setDataSource(path);
 72                 // 设置音频流的类型
 73                 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 74
 75                 // 通过异步的方式装载媒体资源
 76                 mediaPlayer.prepareAsync();
 77                 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
 78                     @Override
 79                     public void onPrepared(MediaPlayer mp) {
 80                         // 装载完成 開始播放流媒体
 81                         mediaPlayer.start();
 82                         Toast.makeText(MainActivity.this, "開始播放", 0).show();
 83                         // 避免反复播放,把播放button设置为不可用
 84                         btn_play.setEnabled(false);
 85                     }
 86                 });
 87                 // 设置循环播放
 88                 // mediaPlayer.setLooping(true);
 89                 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
 90
 91                     @Override
 92                     public void onCompletion(MediaPlayer mp) {
 93                         // 在播放完成被回调
 94                         btn_play.setEnabled(true);
 95                     }
 96                 });
 97
 98                 mediaPlayer.setOnErrorListener(new OnErrorListener() {
 99
100                     @Override
101                     public boolean onError(MediaPlayer mp, int what, int extra) {
102                         // 假设错误发生,又一次播放
103                         replay();
104                         return false;
105                     }
106                 });
107             } catch (Exception e) {
108                 e.printStackTrace();
109                 Toast.makeText(this, "播放失败", 0).show();
110             }
111         } else {
112             Toast.makeText(this, "文件不存在", 0).show();
113         }
114
115     }
116     /**
117      * 暂停
118      */
119     protected void pause() {
120         if (btn_pause.getText().toString().trim().equals("继续")) {
121             btn_pause.setText("暂停");
122             mediaPlayer.start();
123             Toast.makeText(this, "继续播放", 0).show();
124             return;
125         }
126         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
127             mediaPlayer.pause();
128             btn_pause.setText("继续");
129             Toast.makeText(this, "暂停播放", 0).show();
130         }
131
132     }
133
134     /**
135      * 又一次播放
136      */
137     protected void replay() {
138         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
139             mediaPlayer.seekTo(0);
140             Toast.makeText(this, "又一次播放", 0).show();
141             btn_pause.setText("暂停");
142             return;
143         }
144         play();
145     }
146
147     /**
148      * 停止播放
149      */
150     protected void stop() {
151         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
152             mediaPlayer.stop();
153             mediaPlayer.release();
154             mediaPlayer = null;
155             btn_play.setEnabled(true);
156             Toast.makeText(this, "停止播放", 0).show();
157         }
158
159     }
160
161     @Override
162     protected void onDestroy() {
163         // 在activity结束的时候回收资源
164         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
165             mediaPlayer.stop();
166             mediaPlayer.release();
167             mediaPlayer = null;
168         }
169         super.onDestroy();
170     }
171 }

 效果展示:

时间: 2024-11-16 05:55:58

Android开发之Mediaplayer的相关文章

android开发之MediaPlayer+Service MP3播放器

http://blog.csdn.net/zzy916853616/article/details/6450753 [java] view plaincopy import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.List; import android.app.ListActivity; import android.apps.service.Player

Android开发之MediaPlayer和SurfaceView播放视频

使用MediaPlayer出了了可以播放音频之外,还可以播放视频文件,只不过使用MediaPlayer播放视频时,没有提供图像输出界面.可以使用SurfaceView组件来显示视频图像.使用MediaPlayer和SurfaceView播放视频大致可以分为如下四个步骤: 1)定义SurfaceView组件.最好在布局文件中实现. 2)创建MediaPlayer对象,并为其加载要播放的视频. 3)将所播放的视频画面输出到SurfaceView中.使用MediaPlayer对象的setDisplay

Android开发之Mediaplayer状态转换图及音频焦点

前言 之前博客里已经将了MediaPlayer的简单应用,如何使用MediaPlayer在Android应用中播放音频.这篇博客在MediaPlayer使用的基础上,讲解一下MediaPlayer的一些高级功能的使用,以及它的状态转换.对MediaPlayer还不了解的朋友可以先看看之前那篇博客:Android--MP3播放器MediaPlayer. 本篇博客主要内容如下: MediaPlayer的状态变换 MediaPlayer的唤醒锁 MediaPlayer的音频焦点 MediaPlayer

Android开发之SoundPool使用详解

使用SoundPool播放音效 如果应用程序经常播放密集.急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了.因为MediaPlayer存在如下缺点: 1)         延时时间较长,且资源占用率高. 2)         不支持多个音频同时播放. Android中除了MediaPlayer播放音频之外还提供了SoundPool来播放音效,SoundPool使用音效池的概念来管理多个短促的音效,例如它可以开始就加载20个音效,以后在程序中按音效的ID进行播放.

Android开发之MediaRecorder类详解

MediaRecorder类详解 手机一般都有麦克风和摄像头,而Android系统就可以利用这些硬件来录制音视频了. 为了增加对录制音视频的支持,Android系统提供了一个MediaRecorder的类.该类的使用也非常简单,下面让我们来了解一下这个类: 一.类结构: java.lang.Object    ? android.media.MediaRecorder 二.类概述: 用于录制音频和视频的一个类. 三.状态图: 说明: 与MediaPlayer类非常相似MediaRecorder也

Android开发之Sensors与摇一摇

Sensor概述 基于Android的设备有内置的传感器,测量运动,方向,和各种环境条件.这些传感器能够提供原始数据的高精度和准确度,并且是有用的如果你想要监测装置.定位的三维运动,或者你想监控在设备周围环境的变化.例如,一个可能的轨道的读数装置的重力传感器来推断用户的手势和身体的动作复杂,如倾斜.摇晃.旋转.摆动或.同样,一个天气应用程序可能使用的设备的温度传感器和湿度传感器来计算和报告. Android平台支持的传感器三大类: 运动传感器 这些传感器测量加速度的力和旋转力沿三轴.这一类包括加

Android开发之Tween(补间动画)完全解析(下)

欢迎转载,转载请注明出处:http://blog.csdn.net/dmk877/article/details/51980734 在上一篇文章中,我们详细讨论了Tween动画的xml的实现以及interpolator的使用,相信通过上篇文章大家对Tween动画的xml属性的配置会有一个详细的理解,当然这篇文章也是承接上篇文章,所以强烈建议先阅读上篇文章:Android开发之Tween(补间动画)完全解析(上),这篇文章将从代码的角度实现上篇文章的效果.如有疑问请留言,如有谬误欢迎批评指正. T

Android开发之JSON使用

Android开发之JSON使用 今天在论坛看到有不少朋友问关于json的问题,所以想写一篇关于android中使用json的博客. 首先 json是什么 JSON的全称是JavaScript Object Notation,从这里可以看到它源于JavaScript,它采用文本形式体现.比如 {"name":"zhangsan","age":20,"wife":"如花"} 这个简单表示了一个对象,在java

Android开发之bindService()侦听service内部状态

在Android开发之bindService()通信的基础上,实现bindService()方法侦听service内部状态. 实现侦听service内部状态,使用的是回调机制 1.首先实现一个接口 1 public static interface CallBack{ 2 void onDataChange(String data); 3 } 2. 1 private CallBack callBack=null; 2 public void setCallBack(CallBack callB