一 前言
android提供了简单的播放音频和视频的类MediaPlayer,它可以播放raw、assets、sdk、网络上的音视频资源,在前面已经介绍过MediaPlayer(点击查看)。
二 音频播放
播放音频步骤:
(1)创建MediaPlayer对象实例;可以通过new创建该实例,也可以通过静态方法create创建。 (2)装载音频资源,如果在(1)中你使用create创建的MediaPlayer,此时该步骤可省略,否则你将调用setDataSource添加音频资源。 (3)调用prepare()或prepareAsync()方法来做播放前的准备工作,如果(2)省略的话,该步骤也要省略(即如果你掉用setDataSource方法添加音频资源了,就要调用prepare()或prepareAsync()方法做播放前的准备工作,否则就不需要了)。 (4)调用MediaPlayer的start、stop、pause等方法控制播放过程。
1 播放raw中的音频资源文件
首先在res目录创建目录raw ,在raw添加你要播放的音频资源文件,然后就可以按照上述步骤就行了,创建MediaPlayer对象实例代码如下:
private MediaPlayer player;
@AfterViews
void initData(){
player = new MediaPlayer();
// loadRaw();
}
播放音频代码如下:
void loadRaw(){
/*
* 判断音频是否在正在播放,如果是正在播放,
* 就要调用reset方法进行重置,此时player会处于空闲状态,
* 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
*/
if (player.isPlaying()){
// player.release();
player.stop();
}
player.reset();
// player = MediaPlayer.create(this, R.raw.hongyanjiu);
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.hongyanjiu);
try {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
player.prepare();
player.start();
//设置播放监听
setListener();
} catch (IOException e) {
e.printStackTrace();
}
}
说明,需要注意的是在装载资源之前,先要判断是否有资源正在播放,如果有的话就要调用stop停止播放,然后调用reset方法使MediaPlayer处于空闲状态,否则的将会出现非法状态异常。接下来看看是如何设置监听的,这里直接继承了监听类,如下:
public class MainActivity extends AppCompatActivity
implements MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener ,
MediaPlayer.OnPreparedListener,MediaPlayer.OnSeekCompleteListener {
......
}
然后
void setListener(){
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
player.setOnPreparedListener(this);
player.setOnSeekCompleteListener(this);
}
需要实现的方法,如下:
/**
* 音频播放完成调用该方法
* @param mp
*/
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(this, "音频播放完毕", Toast.LENGTH_SHORT).show();
}
/**
* 音频播放错误调用该方法
* @param mp
* @param what 错误类型
* @param extra
* @return
*/
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "音频播放发生错误", Toast.LENGTH_SHORT).show();
return false;
}
/**
* 当方法prepare被调用触发该方法
* @param mp
*/
@Override
public void onPrepared(MediaPlayer mp) {
Toast.makeText(this, "音频播放已就绪", Toast.LENGTH_SHORT).show();
}
/**
* 当调用seek方法时触发该方法
* @param mp
*/
@Override
public void onSeekComplete(MediaPlayer mp) {
Toast.makeText(this, "音频播放已seek", Toast.LENGTH_SHORT).show();
}
2 播放assets中的音频资源文件
首先在src/main目录创建目录assets ,在assets添加你要播放的音频资源文件,然后就可以按照上述步骤就行了,实现fang发如下:
void loadAsset(){
/*
* 判断音频是否在正在播放,如果是正在播放,
* 就要调用reset方法进行重置,此时player会处于空闲状态,
* 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
*/
// player.isLooping()
if (player.isPlaying()){
// player.release();
player.stop();
}
player.reset();
//AssetManage对象
AssetManager am = getAssets();
//打开指定音频文件
try {
AssetFileDescriptor afd = am.openFd("hongyanjiu.mp3");
//给MediaPlayer添加资源文件
player.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
//做准备工作:装载音频 使用setDataSource()方法添加资源 必须再调用prepare()装载音频, 而后才能调用start方法开始播放
afd.close();
player.prepare();
player.start();
setListener();
} catch (IOException e) {
e.printStackTrace();
}
}
说明获取assets资源文件需要用到AssetManage,而AssetManage可以通过Context.getAssets()获取,然后调用AssetManage的openFd方法获取音频资源。
3 播放手机内存中的音频资源文件
在这里我的示例是先把assets中的音频资源copy到手机的sdk里,再来播放资源文件,copy实现代码如下:
public void copyFileFromAssetToSDK(){
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ){
path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + getPackageName();
}else {
path = Environment.getDataDirectory().getAbsolutePath() + File.separator + getPackageName();
}
File file = new File(path);
if (!file.exists()){
file.mkdirs();
}
//AssetManage对象
AssetManager am = getAssets();
try {
AssetFileDescriptor afd = am.openFd("hongyanjiu.mp3");
InputStream is = afd.createInputStream();
// InputStreamReader reader = new InputStreamReader(afd.createInputStream());
// OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(path,"hongyanjiu.mp3")));
File needFile = new File(path,"hongyanjiu.mp3");
// if (!needFile.exists()){
// needFile.mkdirs();
// }
path = needFile.getAbsolutePath();
Log.e("音频文件路径====>", path);
OutputStream os = new FileOutputStream(needFile);
int hasRead = 0;
byte[] buffer = new byte [1024];
while ((hasRead = is.read(buffer)) != -1){
os.write(buffer,0,hasRead);
}
os.flush();
os.close();
is.close();
afd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
然后播放该音频资源代码如下:
void loadSDK(){
/*
* 判断音频是否在正在播放,如果是正在播放,
* 就要调用reset方法进行重置,此时player会处于空闲状态,
* 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
*/
if (player.isPlaying()){
// player.release();
player.stop();
}
player.reset();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
//动态判断手机储存空间的权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == -1 ||
ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE ) == -1){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},0x123);
}else {
try {
copyFileFromAssetToSDK();
if (TextUtils.isEmpty(path)){
return;
}
player.setDataSource(path);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
try {
copyFileFromAssetToSDK();
if (TextUtils.isEmpty(path)){
return;
}
player.setDataSource(path);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4 播放网络音频资源
void loadNet(){
/*
* 判断音频是否在正在播放,如果是正在播放,
* 就要调用reset方法进行重置,此时player会处于空闲状态,
* 如果不进行重置的话,再调用setDataSource设置资源时,会抛出异常 IllegalStateException
*/
if (player.isPlaying()){
player.stop();
}
player.reset();
Uri url = Uri.parse(urlPath);
try {
player.setDataSource(this,url);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
说明,urlPath为网络音频资源地址。最后不要忘记在onDestroy方法释放资源:
@Override
protected void onDestroy() {
super.onDestroy();
if (player.isPlaying()){
player.stop();
player.release();
}
}
完整示例代码点击查看