本文最后更新于:2023年4月15日 下午
本文链接: Android MediaPlayer 播放音频
主要介绍使用MediaPlayer播放音频的方式。关于MediaPlayer的基础知识,比如状态,可以参考Android MediaPlayer 基础简介 。
为了方便表达,定义变量名为mediaPlayer。
可以直接 new MediaPlayer,也可以用MediaPlayer提供的create方法创建。1 mediaPlayer = new MediaPlayer ();
使用create方法创建成功后,mediaPlayer处于Prepared状态。可以直接start播放。1 2 mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file)); mediaPlayer.start();
设置音源 - setDataSource 通过调用setDataSource
来设置音源。setDataSource
有多个重载方法,我们来看常用的几种。
例如设置使用assets里的资源。实际情况可能需要try catch。1 2 3 4 AssetFileDescriptor fd = null ;MediaPlayer mediaPlayer = new MediaPlayer (); fd = context.getApplicationContext().getAssets().openFd(name); mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
本地文件,需要文件的绝对路径。1 mediaPlayer.setDataSource(file.getAbsolutePath());
或者获取文件的Uri来创建mediaPlayer。1 mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
设置网络音频,也是用setDataSource方法,设置url。1 mediaPlayer.setDataSource("https://demo.com/sample.mp3" ));
播放网络音频时,如果使用的是http,有可能会报错1 java.io .IOException : Cleartext HTTP traffic to demo.com not permitted
可以简单地设置一下manifest,设置usesCleartextTraffic=”true”1 2 <application android:usesCleartextTraffic ="true" >
准备 - prepare 同步和异步准备音频资源。prepareAsync()是异步的方式,prepare是同步的。注意线程调度问题,同时不要阻塞UI线程。
使用异步方式准备音频,经常与MediaPlayer.OnPreparedListener监听器配合使用。异步准备时,也可以进行其他的设置。1 2 3 4 5 6 7 mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer .OnPreparedListener() { @Override public void onPrepared (MediaPlayer mediaPlayer) { mediaPlayer.start(); } });
循环播放 - Looping 设置循环播放setLooping。1 mediaPlayer.setLooping(true );
播放完毕后,不会回调OnCompletionListener,而是从头播放当前音频。
播放 - start 播放音频,调用start方法。
处于Prepared,Pause和PlaybackComplete状态时,可以调用start方法,进入Started状态。
暂停 - pause 暂停播放,使用pause方法。在暂停前先判断一下mediaPlayer的是否在播放。
1 2 3 if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); }
暂停成功则处于Paused状态。
停止 - stop 回顾一下MediaPlayer状态切换的图示,我们可以得知在播放中,暂停,播放完成这3个状态下,可以调用stop方法,进入Stopped状态。
调进度 - seekTo 调整播放进度。我们平时使用音乐播放软件一般都会有这个功能。 seekTo方法接受一个毫秒参数。
1 2 int targetMS = (int ) (percent * mediaPlayer.getDuration()); mediaPlayer.seekTo(targetMS);
seekTo并不会改变MediaPlayer的状态。
重置 - reset reset后的mediaPlayer进入Idle状态。需要重新设置音源与准备。
释放 - release 不再使用这个mediaPlayer时,应当尽快释放掉,以释放相关的资源。 调用release后,mediaPlayer进入End状态。此时这个mediaPlayer就不能再使用了。
常用监听器 缓冲监听器 OnBufferingUpdateListener 比如我们加载网络音频的时候,常用这个监听器来监听缓冲进度。显示缓冲进度,也可以提高用户体验。
1 2 3 4 5 6 7 mMediaPlayer.prepareAsync(); mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer .OnBufferingUpdateListener() { @Override public void onBufferingUpdate (MediaPlayer mp, int percent) { } });
错误监听器 OnErrorListener 1 2 3 4 5 6 mediaPlayer.setOnErrorListener(new MediaPlayer .OnErrorListener() { @Override public boolean onError (MediaPlayer mediaPlayer, int i, int i1) { return true ; } });
注意onError的返回值。可以选择自己处理error。
1 2 3 4 5 * @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 1 2 3 4 5 6 mediaPlayer.setOnCompletionListener(new MediaPlayer .OnCompletionListener() { @Override public void onCompletion (MediaPlayer mediaPlayer) { } });
使用示例 播放assets里的音频 播放assets里的音频文件,使用到AssetFileDescriptor类。使用后记得关闭AssetFileDescriptor。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 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); } } } }
播放本地音频文件 尝试播放音频文件。仅播放一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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,播放在线音频
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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 基础简介
Android MediaPlayer 播放音频
Android 使用URLConnection下载音频文件
Android MediaPlayer 音频倍速播放,调整播放速度
Android音视频相关文章请参考 https://rustfisher.com/tags/Android-Media/