这次首先实现了播放音频的功能,日后用于语音聊天,通过自定义一个AudioPlayManager类来实现这个功能。
/**
* 播放音频文件
*
* @param path 音频文件路径
* @param listener 播放监听器
*/
public static void playAudio(Context context, final String path, final OnPlayAudioListener listener) {
if (sAudioManager == null) {
sAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
assert sAudioManager != null;
sAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
if (sMediaPlayer == null) {
sMediaPlayer = new MediaPlayer();
} else {
if (sMediaPlayer.isPlaying()) {
sMediaPlayer.stop();
}
sMediaPlayer.reset();
}
sMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
if (listener != null) {
listener.onPlay();
}
}
});
sMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
if (listener != null) {
listener.onError("播放出错,错误码:" + what);
}
return false;
}
});
sMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (listener != null) {
listener.onComplete();
}
}
});
try {
int focus = sAudioManager.requestAudioFocus(null,
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
if (focus == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
sMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
sMediaPlayer.setDataSource(path);
sMediaPlayer.prepare();
} else if (focus == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
if (listener != null) {
listener.onError("播放出错:" + "AUDIOFOCUS_REQUEST_FAILED");
}
}
} catch (Exception e) {
if (listener != null) {
listener.onError("播放出错:" + e.getMessage());
}
release();
}
}
其中的listener监听器的接口
public interface OnPlayAudioListener {
void onPlay();
void onComplete();
void onError(String message);
}
接口的实现
AudioPlayManager.playAudio(this, audioAttachment.getPath(),
new AudioPlayManager.OnPlayAudioListener() {
@Override
public void onPlay() {
// 启动播放动画
isAudioPlay = true;
mPlayId = message.getUuid();
mAudioPlayHandler.startAudioAnim(imageView, isLeft);
}
@Override
public void onComplete() {
isAudioPlay = false;
mPlayId = "";
mAudioPlayHandler.stopAnimTimer();
}
@Override
public void onError(String message) {
isAudioPlay = false;
mPlayId = "";
mAudioPlayHandler.stopAnimTimer();
ToastUtils.showMessage(P2PChatActivity.this, message);
}
});
暂停播放,在contex生命周期onPause中调用
public static void pause() {
if (sMediaPlayer != null && sMediaPlayer.isPlaying()) { //正在播放的时候
sMediaPlayer.pause();
isPause = true;
}
if (sAudioManager != null) {
sAudioManager.abandonAudioFocus(null);
}
}
恢复播放,在contex生命周期onResume中调用
public static void resume() {
if (sMediaPlayer != null && isPause) {
if (sAudioManager != null) {
int focus = sAudioManager.requestAudioFocus(null,
AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
if (focus == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
sMediaPlayer.start();
isPause = false;
}
}
}
}
释放资源,在context生命周期onDestroy中调用
public static void release() {
if (sMediaPlayer != null) {
sMediaPlayer.release();
sMediaPlayer = null;
}
if (sAudioManager != null) {
sAudioManager.abandonAudioFocus(null);
sAudioManager = null;
}
}
然后自定义了一个Handler用来播放音频文件,并通过更新界面实现动画效果。
//语音动画控制器
private Timer mTimer = null;
//语音动画控制任务
private TimerTask mTimerTask = null;
//记录语音动画图片索引
private int index = 0;
//根据 index 更换动画
private AudioAnimHandler mAudioAnimHandler = null;
类的构造方法继承自Handler:
private static class AudioAnimHandler extends Handler {
private final ImageView mIvAudio;
private final boolean isLeft;
private int[] mLeftIndex = {
R.mipmap.sound_left_1,R.mipmap.sound_left_2,R.mipmap.sound_left_3};
private int[] mRightIndex = {
R.mipmap.sound_right_1, R.mipmap.sound_right_2,R.mipmap.sound_right_3};
AudioAnimHandler(ImageView imageView,boolean isLeft){
this.mIvAudio = imageView;
this.isLeft = isLeft;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 0:
mIvAudio.setImageResource(isLeft? mLeftIndex[0]:mRightIndex[0]);
break;
case 1:
mIvAudio.setImageResource(isLeft? mLeftIndex[1]:mRightIndex[1]);
break;
case 2:
mIvAudio.setImageResource(isLeft? mLeftIndex[2]:mRightIndex[2]);
break;
default:
mIvAudio.setImageResource(isLeft? R.mipmap.sound_left_0:R.mipmap.sound_right_0);
removeCallbacks(null);
break;
}
}
}
播放音频动画的方法:
public void startAudioAnim(ImageView imageView,boolean isLeft){
stopAnimTimer();
// 语音播放动画效果
mAudioAnimHandler = new AudioAnimHandler(imageView,isLeft);
mTimerTask = new TimerTask() {
@Override
public void run() {
mAudioAnimHandler.obtainMessage(index).sendToTarget();
index = (index+1)%3;
}
};
mTimer = new Timer();
// 每半秒更新一次界面
mTimer.schedule(mTimerTask,0,500);
}
停止播放音频动画的方法:
public void stopAnimTimer(){
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
if (mTimerTask != null) {
mTimerTask.cancel();
mTimerTask = null;
}
// 将上一个语音消息界面复位
if (mAudioAnimHandler != null){
mAudioAnimHandler.obtainMessage(3).sendToTarget();
}
}
在日后的编程中在需要播放音频的Java文件中调用这些类和方法。