深入Android MediaPlayer的使用方法详解

article/2025/10/2 0:06:02
1)如何获得MediaPlayer实例:
可以使用直接new的方式:
MediaPlayer mp = new MediaPlayer();
也可以使用create的方式,如:
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了

2) 如何设置要播放的文件:
MediaPlayer要播放的文件主要包括3个来源:
a. 用户在应用中事先自带的resource资源
例如:MediaPlayer.create(this, R.raw.test);
b. 存储在SD卡或其他文件路径下的媒体文件
例如:mp.setDataSource("/sdcard/test.mp3");
c. 网络上的媒体文件
例如:mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");

MediaPlayer的setDataSource一共四个方法:
setDataSource (String path) 
setDataSource (FileDescriptor fd) 
setDataSource (Context context, Uri uri) 
setDataSource (FileDescriptor fd, long offset, long length)
 
其中使用FileDescriptor时,需要将文件放到与res文件夹平级的assets文件夹里,然后使用:
AssetFileDescriptor fileDescriptor = getAssets().openFd("rain.mp3");
m_mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),fileDescriptor.getStartOffset(), fileDescriptor.getLength());

来设置datasource

Android提供了常见的音频、视频的编码、解码机制。借助于多媒体类MediaPlayer的支持,开发人员可以很方便在在应用中播放音频、视频。本篇博客主要讲解在Android平台下如何播放一个音频文件。

  本篇博客主要内容如下:

  • MediaPlayer
  • MediaPlayer的音频源
  • 使用MediaPlayer播放音乐
  • MediaPlayer使用技巧
  • Demo--一个简单的MP3播放器

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卡的资源:

view source print ?
1.1                 mediaPlayer = new MediaPlayer();
2.2                 mediaPlayer.setDataSource("/sdcarc/a.mp3");

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

view source print ?
1.<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>

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

view source print ?
1.1                 mediaPlayer = new MediaPlayer();
2.2                 mediaPlayer.setDataSource(http://192.168.1.102:1231/music/a.mp3);

 如果访问网络流媒体资源,还需要设置访问网络的权限:

view source print ?
1.<uses-permission android:name="android.permission.INTERNET"></uses-permission>

使用MediaPlayer播放音乐

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

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

  • void statr():开始或恢复播放。
  • 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)错误。

view source print ?

01.1                 mediaPlayer = new MediaPlayer();
02.2                 mediaPlayer.setDataSource(path);
03.3                 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
04.4                
05.5                 // 通过异步的方式装载媒体资源
06.6                 mediaPlayer.prepareAsync();
07.7                 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {                   
08.8                     @Override
09.9                     public void onPrepared(MediaPlayer mp) {
10.10                         // 装载完毕回调
11.11                         mediaPlayer.start();
12.12                     }
13.13                 });

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

view source print ?
1.1         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
2.2             mediaPlayer.stop();
3.3             mediaPlayer.release();
4.4             mediaPlayer = null;
5.5         }
3、使用MediaPlayer最好使用一个Service来使用,并且在Service的onDestory()方法中回收MediaPlayer资源,实际上,就算是直接使用Activity承载MediaPlayer,也最好在销毁的时候判断一下MediaPlayer是否被回收,如果未被回收,回收其资源,因为底层调用的native方法,如果不销毁还是会在底层继续播放,而承载的组件已经被销毁了,这个时候就无法获取到这个MediaPlayer进而控制它。
view source print ?
01.1     @Override
02.2     protected void onDestroy() {
03.3         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
04.4             mediaPlayer.stop();
05.5             mediaPlayer.release();
06.6             mediaPlayer = null;
07.7         }
08.8         super.onDestroy();
09.9     }

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

view source print ?
01.1                 // 设置循环播放
02.2 //                mediaPlayer.setLooping(true);
03.3                 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
04.4                    
05.5                     @Override
06.6                     public void onCompletion(MediaPlayer mp) {
07.7                         // 在播放完毕被回调
08.8                         play();                       
09.9                     }
10.10                 });

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

view source print ?

1.1                 mediaPlayer.setOnErrorListener(new OnErrorListener() {
2.2                    
3.3                     @Override
4.4                     public boolean onError(MediaPlayer mp, int what, int extra) {
5.5                         play();
6.6                         return false;
7.7                     }
8.8                 });

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

  上面已经介绍了MediaPlayer播放一段音频文件的所有需要用到的内容。下面通过一个简单的Demo来演示如何使用MediaPlayer播放一个SD卡上的MP3文件。操作MediaPlayer应该放在Service中完成,这里为了简单,使用Activity直接操作MediaPlayer。代码注释里写的很清楚里,这里不再累述。

  执行这个示例需要在/sdcard/目录下存在xm.mp3的文件。  

view source print ?
001.1 package cn.bgxt.mediaplayerdemo;
002.2
003.3 import java.io.File;
004.4 import android.media.AudioManager;
005.5 import android.media.MediaPlayer;
006.6 import android.media.MediaPlayer.OnCompletionListener;
007.7 import android.media.MediaPlayer.OnErrorListener;
008.8 import android.media.MediaPlayer.OnPreparedListener;
009.9 import android.os.Bundle;
010.10 import android.app.Activity;
011.11 import android.view.View;
012.12 import android.widget.Button;
013.13 import android.widget.EditText;
014.14 import android.widget.Toast;
015.15
016.16 public class MainActivity extends Activity {
017.17     private EditText et_path;
018.18     private Button btn_play, btn_pause, btn_replay, btn_stop;
019.19     private MediaPlayer mediaPlayer;
020.20
021.21     @Override
022.22     protected void onCreate(Bundle savedInstanceState) {
023.23         super.onCreate(savedInstanceState);
024.24         setContentView(R.layout.activity_main);
025.25
026.26         et_path = (EditText) findViewById(R.id.et_path);
027.27         btn_play = (Button) findViewById(R.id.btn_play);
028.28         btn_pause = (Button) findViewById(R.id.btn_pause);
029.29         btn_replay = (Button) findViewById(R.id.btn_replay);
030.30         btn_stop = (Button) findViewById(R.id.btn_stop);
031.31
032.32         btn_play.setOnClickListener(click);
033.33         btn_pause.setOnClickListener(click);
034.34         btn_replay.setOnClickListener(click);
035.35         btn_stop.setOnClickListener(click);
036.36     }
037.37
038.38     private View.OnClickListener click = new View.OnClickListener() {
039.39
040.40         @Override
041.41         public void onClick(View v) {
042.42
043.43             switch (v.getId()) {
044.44             case R.id.btn_play:
045.45                 play();
046.46                 break;
047.47             case R.id.btn_pause:
048.48                 pause();
049.49                 break;
050.50             case R.id.btn_replay:
051.51                 replay();
052.52                 break;
053.53             case R.id.btn_stop:
054.54                 stop();
055.55                 break;
056.56             default:
057.57                 break;
058.58             }
059.59         }
060.60     };
061.61     /**
062.62      * 播放音乐
063.63      */
064.64     protected void play() {
065.65         String path = et_path.getText().toString().trim();
066.66         File file = new File(path);
067.67         if (file.exists() && file.length() > 0) {
068.68             try {
069.69                 mediaPlayer = new MediaPlayer();
070.70                 // 设置指定的流媒体地址
071.71                 mediaPlayer.setDataSource(path);
072.72                 // 设置音频流的类型
073.73                 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
074.74
075.75                 // 通过异步的方式装载媒体资源
076.76                 mediaPlayer.prepareAsync();
077.77                 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
078.78                     @Override
079.79                     public void onPrepared(MediaPlayer mp) {
080.80                         // 装载完毕 开始播放流媒体
081.81                         mediaPlayer.start();
082.82                         Toast.makeText(MainActivity.this, "开始播放", 0).show();
083.83                         // 避免重复播放,把播放按钮设置为不可用
084.84                         btn_play.setEnabled(false);
085.85                     }
086.86                 });
087.87                 // 设置循环播放
088.88                 // mediaPlayer.setLooping(true);
089.89                 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
090.90
091.91                     @Override
092.92                     public void onCompletion(MediaPlayer mp) {
093.93                         // 在播放完毕被回调
094.94                         btn_play.setEnabled(true);
095.95                     }
096.96                 });
097.97
098.98                 mediaPlayer.setOnErrorListener(new OnErrorListener() {
099.99
100.100                     @Override
101.101                     public boolean onError(MediaPlayer mp, int what, int extra) {
102.102                         // 如果发生错误,重新播放
103.103                         replay();
104.104                         return false;
105.105                     }
106.106                 });
107.107             } catch (Exception e) {
108.108                 e.printStackTrace();
109.109                 Toast.makeText(this, "播放失败", 0).show();
110.110             }
111.111         } else {
112.112             Toast.makeText(this, "文件不存在", 0).show();
113.113         }
114.114
115.115     }
116.116     /**
117.117      * 暂停
118.118      */
119.119     protected void pause() {
120.120         if (btn_pause.getText().toString().trim().equals("继续")) {
121.121             btn_pause.setText("暂停");
122.122             mediaPlayer.start();
123.123             Toast.makeText(this, "继续播放", 0).show();
124.124             return;
125.125         }
126.126         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
127.127             mediaPlayer.pause();
128.128             btn_pause.setText("继续");
129.129             Toast.makeText(this, "暂停播放", 0).show();
130.130         }
131.131
132.132     }
133.133    
134.134     /**
135.135      * 重新播放
136.136      */
137.137     protected void replay() {
138.138         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
139.139             mediaPlayer.seekTo(0);
140.140             Toast.makeText(this, "重新播放", 0).show();
141.141             btn_pause.setText("暂停");
142.142             return;
143.143         }       
144.144         play();
145.145     }
146.146    
147.147     /**
148.148      * 停止播放
149.149      */
150.150     protected void stop() {
151.151         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
152.152             mediaPlayer.stop();
153.153             mediaPlayer.release();
154.154             mediaPlayer = null;
155.155             btn_play.setEnabled(true);
156.156             Toast.makeText(this, "停止播放", 0).show();
157.157         }
158.158
159.159     }
160.160
161.161     @Override
162.162     protected void onDestroy() {
163.163         // 在activity结束的时候回收资源
164.164         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
165.165             mediaPlayer.stop();
166.166             mediaPlayer.release();
167.167             mediaPlayer = null;
168.168         }
169.169         super.onDestroy();
170.170     }
171.171 }



转自文章   http://www.jb51.net/article/38722.htm

http://www.it165.net/pro/html/201311/7881.html







http://chatgpt.dhexx.cn/article/JNOi842I.shtml

相关文章

Android MediaPlayer状态机

翻译Android Reference Manual的MediaPlayer的状态机 对播放音频/视频文件和流的控制是通过一个状态机来管理的。下图显示一个MediaPlayer对象被支持的播放控制操作驱动的生命周期和状态。椭圆代表MediaPlayer对象可能驻留的状态。弧线表示驱动MediaPlayer在各个状态之间迁移的…

Android提高第二十一篇之MediaPlayer播放网络视频

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; 上次讲解了MediaPlayer播放网络音频&#xff0c;介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法&#xff0c;这次再讲解MediaPlayer播放网络视频。播放网络视频比播放网络音频多需要…

Android开发之MediaPlayer详解

Android开发之MdiaPlayer详解 MediaPlayer类可用于控制音频/视频文件或流的播放&#xff0c;我曾在《Android开发之基于Service的音乐播放器》一文中介绍过它的使用。下面让我们看一下MediaPlayer类的详细介绍。 一、类结构&#xff1a; java.lang.Object ↳ android.med…

Android 9.0 MediaPlayer播放流程分析

1.MediaPlayer初始化流程 EventHandler是后面处理数据回调的handler. 在AudioFlinger.cpp中获取nextUniqueId&#xff1a; audio_unique_id_t AudioFlinger::nextUniqueId(audio_unique_id_use_t use) {// This is the internal API, so it is OK to assert on bad parameter.…

Android的MediaPlayer架构介绍

本文主要介绍的是Android中很重要也最为复杂的媒体播放器&#xff08;MediaPlayer&#xff09;部分的架构。对于Android这样一个完整又相对复杂的系统&#xff0c;一个MediaPlayer功能的实现不在其具体的功能&#xff0c;而是具体功能如何适应Android系统Android MediaPlayer的…

Android之MediaPlayer详解

文章转自&#xff1a;http://www.cnblogs.com/gansc23/archive/2011/04/08/2009868.html MediaPlayer类可用于控制音频/视频文件或流的播放。关于如何使用这个类的方法还可以阅读VideoView类的文档。 1&#xff0e;状态图 对播放音频/视频文件和流的控制是通过一个状态机来…

Android MediaPlayer播放视频详细步骤

MediaPlayer类是媒体框架最重要的组成部分之一&#xff0c;此类的对象能够获取&#xff0c;解码以及播放音频和视频&#xff0c;而且只需极少量设置&#xff0c;它支持多种不同的媒体源&#xff0c;例如&#xff1a; 本地资源 内部Url&#xff0c;例如您可能从内容解析器获取U…

Android MediaPlayer

最近在做游戏状态的保存时&#xff0c;需要存储背景音乐是否静音了&#xff0c;一直不成功&#xff0c;并且总是报出如下错误&#xff1a; ERROR/MediaPlayer(9974): start called in state 64 ERROR/MediaPlayer(9974): error (-38, 0) ERROR/MediaPlayer(9974): Error (-38…

MediaPlayer类播放音频

一、MediaPlayer类 1、常用方法 方法名称功能setDataSource()设置要播放的音频文件prepare()在开始播放前。调用该方法准备播放start()开始播放或者继续播放音频pause()暂停播放reset()重置MediaPlayer对象seekTo()从指定位置播放stop()停止播放&#xff0c;调用后MediaPlaye…

Android提高第一篇之MediaPlayer

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; 前面写了十四篇关于界面的入门文章&#xff0c;大家都看完和跟着练习之后&#xff0c;对于常用的Layout和View都会有一定的了解了,接下来的文章就不再强调介绍界面了&#xff0c;而是针对具体…

Android中的MediaPlayer的使用详解

今天本文介绍的是Andriod系统自带的Mediaplayer,和VideoView实现简单的音乐和视频的播放&#xff0c;至于想做出如酷狗音乐这样的APP的话&#xff0c;只要想做&#xff0c;应该也不难&#xff0c;都是基于此实现了功能的扩展。 Android的MediaPlayer包含了Audio和Video的播放功…

MediaPlayer详解和使用

Android多媒体相关的API&#xff0c;网上基本都能找到很多相关的文章&#xff0c;使用起来也很简单&#xff0c;一直在犹豫要不要写这方面的内容&#xff0c;后来决定还是写一写&#xff0c;一方面算是一个归纳总结&#xff0c;另一方面&#xff0c;也方便以后查阅。这一篇就写…

MediaPlayer的使用

MediaPlayer的使用 MediaPlayer的使用&#xff08;2019.07.16&#xff09;1.视频播放器的原理2.Android系统自带的MediaPlay状态机详解&#xff08;MediaPlay的生命周期&#xff09;3.如何使用MediaPlayer播放音频与视频&#xff08;一 &#xff09;播放音频&#xff08;二&…

MediaPlayer使用以及常见问题

前面已经写过一篇类似的文章&#xff0c;但是还不够细致&#xff1a; 采用Android的MediaPlayerSurfaceView设计视频播放器 这里我们重新理一下&#xff0c;并记录一点实际运用时遇到的问题。 MediaPlayer特性 MediaPlayer类用于控制音频文件、视频文件和流的播放。 Media…

Android MediaPlayer类

1. MediaPlayer方法 MediaPlayer创建 可以直接调用构造函数&#xff0c;利用setDataSource()方法设置资源。MediaPlayer mp new MediaPlayer(); // path可以是本地路径&#xff0c;也可以是网络地址 mp.setDataSource(String path);也可以调用create()方法&#xff0c;create…

MediaPlayer状态图及生命周期

MediaPlayer状态图及生命周期 MediaPlayer是Android中的uoge多媒体播放类&#xff0c;我们能通过它控制音视频流或本地音视频资源的播放过程。 这一片博客主要介绍MediaPlayer状态图及生命周期。先看一张官网很经典的MediaPlayer状态机的图片。 其中椭圆代表MediaPlayer驻留…

Android 使用MediaPlayer播放音频详解

目录 一、官方资料 二、简单介绍 三、MediaPlayer使用 1.创建MediaPlayer实例 2.重要API 3.状态图 4.代码 5.常用API 6.辅助效果 总结 一、官方资料 MediaPlayer 概览https://developer.android.google.cn/guide/topics/media/mediaplayer?hlzh_cn MediaPlayer 文…

Android -- 多媒体播放之MediaPlayer基础简介

Android -- MediaPlayer基础简介 MediaPlayer是Android中的一个多媒体播放类&#xff0c;我们能通过它控制音视频流或本地音视频资源的播放过程。 这段时间查阅了Android官方文档对MediaPlayer的介绍&#xff0c;同时也看了一些书籍介绍。现在把MediaPlayer的基础内容在此做一…

网易雷火9.18笔试题

3小时的题 我迟到了1个小时&#xff0c;提前了40分钟润&#xff0c;花了1个小时20分钟&#xff08;中途有点其他事&#xff09;&#xff0c;a了2道&#xff0c;第三题没思路&#xff0c;第4题不想看&#xff0c;就这样吧 #include <iostream> using namespace std; int…

网易笔试题总结

var string string; var number 0; var bool true; console.log(number || string); console.log(number && string); console.log(bool || number); console.log(bool && number); 输出结果 如果换下string和num的位置呢 var string string1; var numbe…