本文链接: Android MediaPlayer 播放音频

主要介绍使用MediaPlayer播放音频的方式。关于MediaPlayer的基础知识,比如状态,可以参考Android MediaPlayer 基础简介。

为了方便表达,定义变量名为mediaPlayer。

MediaPlayer的使用方式

创建MediaPlayer

可以直接 new MediaPlayer,也可以用MediaPlayer提供的create方法创建。

mediaPlayer = new MediaPlayer();

使用create方法创建成功后,mediaPlayer处于Prepared状态。可以直接start播放。

    mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
mediaPlayer.start();

设置音源 - setDataSource

通过调用setDataSource来设置音源。setDataSource有多个重载方法,我们来看常用的几种。

例如设置使用assets里的资源。实际情况可能需要try catch。

    AssetFileDescriptor fd = null;
MediaPlayer mediaPlayer = new MediaPlayer();
fd = context.getApplicationContext().getAssets().openFd(name);
mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());

本地文件,需要文件的绝对路径。

mediaPlayer.setDataSource(file.getAbsolutePath());

或者获取文件的Uri来创建mediaPlayer。

mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));

设置网络音频,也是用setDataSource方法,设置url。

mediaPlayer.setDataSource("https://demo.com/sample.mp3"));

播放网络音频时,如果使用的是http,有可能会报错

java.io.IOException: Cleartext HTTP traffic to demo.com not permitted

可以简单地设置一下manifest,设置usesCleartextTraffic="true"

<application
android:usesCleartextTraffic="true">

准备 - prepare

同步和异步准备音频资源。prepareAsync()是异步的方式,prepare是同步的。注意线程调度问题,同时不要阻塞UI线程。

使用异步方式准备音频,经常与MediaPlayer.OnPreparedListener监听器配合使用。异步准备时,也可以进行其他的设置。

    mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start(); // 准备好了就播放
}
});

循环播放 - Looping

设置循环播放setLooping。

mediaPlayer.setLooping(true);

播放完毕后,不会回调OnCompletionListener,而是从头播放当前音频。

播放 - start

播放音频,调用start方法。

mediaPlayer.start();

处于Prepared,Pause和PlaybackComplete状态时,可以调用start方法,进入Started状态。

暂停 - pause

暂停播放,使用pause方法。在暂停前先判断一下mediaPlayer的是否在播放。

    if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}

暂停成功则处于Paused状态。

停止 - stop

回顾一下MediaPlayer状态切换的图示,我们可以得知在播放中,暂停,播放完成这3个状态下,可以调用stop方法,进入Stopped状态。

mediaPlayer.stop();

调进度 - seekTo

调整播放进度。我们平时使用音乐播放软件一般都会有这个功能。

seekTo方法接受一个毫秒参数。

    int targetMS = (int) (percent * mediaPlayer.getDuration());
mediaPlayer.seekTo(targetMS);

seekTo并不会改变MediaPlayer的状态。

重置 - reset

reset后的mediaPlayer进入Idle状态。需要重新设置音源与准备。

释放 - release

不再使用这个mediaPlayer时,应当尽快释放掉,以释放相关的资源。

调用release后,mediaPlayer进入End状态。此时这个mediaPlayer就不能再使用了。

常用监听器

缓冲监听器 OnBufferingUpdateListener

比如我们加载网络音频的时候,常用这个监听器来监听缓冲进度。显示缓冲进度,也可以提高用户体验。

    mMediaPlayer.prepareAsync();
mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// percent代表缓冲百分比
}
});

错误监听器 OnErrorListener

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return true; // 返回true表示在此处理错误,不会回调onCompletion
}
});

注意onError的返回值。可以选择自己处理error。

         * @return True if the method handled the error, false if it didn't.
* Returning false, or not having an OnErrorListener at all, will
* cause the OnCompletionListener to be called.
*/
boolean onError(MediaPlayer mp, int what, int extra);

播放完毕监听器 OnCompletionListener

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
// 播放完毕
}
});

使用示例

播放assets里的音频

播放assets里的音频文件,使用到AssetFileDescriptor类。使用后记得关闭AssetFileDescriptor。

    private void playAssetsAudio(final String name, Context context) {
Log.d(TAG, "playAssetWordSound: try to play assets sound file. -> " + name);
AssetFileDescriptor fd = null;
try {
MediaPlayer mediaPlayer;
Log.v(TAG, "Looking in assets.");
fd = context.getApplicationContext().getAssets().openFd(name);
mediaPlayer = new MediaPlayer();
mediaPlayer.reset();
mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG, "onPrepared: " + name);
mediaPlayer.start();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
Log.d(TAG, "onCompletion: " + name);
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int i, int i1) {
mp.release();
return true;
}
});
} catch (Exception e) {
try {
if (fd != null) {
fd.close();
}
} catch (Exception e1) {
Log.e(TAG, "Exception close fd: ", e1);
}
} finally {
if (fd != null) {
try {
fd.close();
} catch (IOException e) {
Log.e(TAG, "Finally, close fd ", e);
}
}
}
}

播放本地音频文件

尝试播放音频文件。仅播放一次。

    private void playAudioFile(final File file) {
Log.d(TAG, "playAudioFile: " + file.getAbsolutePath());
MediaPlayer mediaPlayer;
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setLooping(false);
mediaPlayer.setDataSource(file.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
Log.d(TAG, "Play local sound onError: " + i + ", " + i1);
return true;
}
});
} catch (Exception e) {
Log.e(TAG, "playAudioFile: ", e);
}
}

播放在线音频

设置url,播放在线音频

    private void playOnlineSound(String soundUrlDict) {
try {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(soundUrlDict);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (mp != null) {
mp.release();
}
Log.d(TAG, "onCompletion: play sound.");
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
Log.d(TAG, "Play online sound onError: " + i + ", " + i1);
return false;
}
});
} catch (IOException e1) {
Log.e(TAG, "url: ", e1);
}
}

代码可以参考示例工程: https://github.com/RustFisher/android-MediaPlayer

Android MediaPlayer 播放音频的更多相关文章

  1. Android(java)学习笔记180:Android MediaPlayer 播放prepareAsync called in state 8解决办法

    使用android MediaPlayer播放音频文件时,有时会出现prepareasync called in state 8错误. 以下方法可以避免这个异常出现.  第一种方法: private ...

  2. Android(java)学习笔记123:Android MediaPlayer 播放prepareAsync called in state 8解决办法

    1. 使用android MediaPlayer播放音频文件时,有时会出现prepareasync called in state 8错误. 以下方法可以避免这个异常出现.  第1种方法: priva ...

  3. Android学习总结(十六) ———— MediaPlayer播放音频与视频

    一.基本概念 本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.Android的MediaPlayer包含了Audio和video的播放功能,在Andr ...

  4. 【Android】播放音频的几种方式介绍

    接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...

  5. MediaPlayer播放音频,也可以播放视频

    使用MediaPlayer播放音频或者视频的最简单例子: JAVA代码部分: public class MediaPlayerStudy extends Activity { private Butt ...

  6. Android MediaPlayer播放一般音频与SoundPool播放短促的音效

    [1]使用MediaPlayer实现一般的音频播放 MediaPlayer播放通常的音频文件 MediaPlayer mediaPlayer = new MediaPlayer(); if (medi ...

  7. 使用MediaPlayer播放音频-----之二

    MediaPlayer播放不同来源的音频文件: 一.播放应用的资源文件 1.调用MediaPlayer的create(Context  context , int  resid)方法加载指定资源文件. ...

  8. 使用MediaPlayer播放音频-----之一

    MediaPlayer提供了如下方法来指定装载相应的音频文件: 1.void  setDataSource( String  path):指定装载path路径所代表的文件. 2.void  setDa ...

  9. 【转】解决在Android设备播放音频与其他应用重音的问题,并监听耳机的控制按钮

    概述 在安卓开发中免不了需要播放一点音乐了,音频了.但是这时候有别的应用正在播放,这时候就会出现重音的现象,完全影响用户体验,我们的项目就遇上了这样的尴尬,然后查找了一些文档,记录一下: 管理音频焦点 ...

随机推荐

  1. 一文看懂ConstraintLayout的用法

    ConstraintLayout 相对于 RelativeLayout来说性能更好,布局上也更加灵活.在最新的Google Android开发文档中是推荐使用 ConstraintLayout的,下面 ...

  2. python学习笔记(3)--函数、参数、变量、递归

    1.函数基本语法和特性 背景摘要 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏出了所有的知识量吗,写出了以下代码 whi ...

  3. Python 字符串的所有方法详解

    name = "my name is {name} and my age is {age}" # 首字母大写 name.capitalize() # 统计某个字符的个数 name. ...

  4. 在github上搭建个人博客并在线更新

    换博客比更博还勤的我终于决定写一篇博客搭建教程了.. FAQ Q:\(hexo\)需要本地编译.\(jekyll\)虽然可以直接上传\(md\)..但是如果在github上直接编译也太难受了叭,毕竟不 ...

  5. AR+工业,带来哪些革变呢?

            随着技术的普及相信大家对VR和AR也略有所知,尤其是AR增强现实技术,已经成为许多科技巨头企业争相扩疆的热土,目前来说,AR技术最广泛的应用是工业领域,已经显示出巨大的价值.     ...

  6. 从 View 的四个构造方法说起

    View 类的四个构造函数 写过自定义 View 的都知道,View 有四个构造函数,一般大家都知道第一个构造方法是简单的在代码中new View 的时候调用的,第二个构造方法使用最广泛,是对应的生成 ...

  7. python 29 Socket - 套接字

    目录 Socket - 套接字 Socket - 套接字 应用层与TCP/IP协议族通信层(或传输层)之间的抽象层,是一组接口()接收数据:当接口接收数据之后,交由操作系统: 如果数据与操作系统直接交 ...

  8. RocketMQ 4.3.2 standalone Installation and Configuration

    1 Download RockeMQ Package: You need to download it and put it to the OS Image. wget http://apache.c ...

  9. spss数据分析可以被人工智能替换吗

    作为一名需要对课题进行研究的大学生,我在日常学习中经常需要用到spss,虽然老师上课已经初步教了我如何用这个软件,然而,在使用过程中我还是遇到了许多问题.具体来说,就是这个软件在很多地方都不够与时俱进 ...

  10. 解决npm报错:Module build failed: TypeError: this.getResolve is not a function

    1.sass-loader的版本过高导致的编译错误,当前最高版本是8.x,需要退回到7.3.1 运行: npm uninstall sass-loader --save-dev(卸载当前版本) npm ...