Android Media
更新日期: 2022-8-22
2022-8-22 更新说明
2022-8-9 增加播放例子
主要介绍使用MediaPlayer播放音频的方式。关于MediaPlayer的基础知识,比如状态,可以参考Android 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 ());
或者使用文件拿到FileDescriptor
,也需要try catch
FileInputStream fis = new FileInputStream ( wavFile );
mediaPlayer . setDataSource ( fis . getFD ());
MediaPlayer报错 (1, -2147483648)
有人遇到过MediaPlayer报错 (1, -2147483648),可尝试用FileDescriptor
来setDataSource
,规避错误
StackOverflow
本地文件,需要文件的绝对路径。
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方法。
处于Prepared,Pause和PlaybackComplete状态时,可以调用start方法,进入Started状态。
暂停 - pause
暂停播放,使用pause方法。在暂停前先判断一下mediaPlayer的是否在播放。
if ( mediaPlayer . isPlaying ()) {
mediaPlayer . pause ();
}
暂停成功则处于Paused状态。
停止 - stop
回顾一下MediaPlayer状态切换的图示,我们可以得知在播放中,暂停,播放完成这3个状态下,可以调用stop方法,进入Stopped状态。
调进度 - 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
参考
本文也发布在
cnblog
掘金
简书
51CTO
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~
📖AndroidTutorial
📚AndroidTutorial
🙋反馈问题
🔥最近更新
🍪投喂作者
Ads