Android MediaPlayer 播放音频

本贴最后更新于 2044 天前,其中的信息可能已经水流花落

本文链接: 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

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    335 引用 • 324 回帖 • 1 关注
  • mediaplayer
    3 引用

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...