语音播放与录音 (五分钟学会用 非常全面)

项目用到的技术点和亮点

  1. 语音录音 (单个和列表)
  2. 语音播放(单个和列表)
  3. 语音录音封装
  4. 语音播放器封装
  5. 语音列表顺序播放
  6. 语音列表单个播放 复用问题处理

因为安装原生录音不能录mp3格式文件 而mp3格式是安卓和ios公用的,所以我们需要的是能直接录取mp3文件或者录完的格式转成mp3格式
下面添加这个库 能直接录mp3文件,我觉得是最方便的
compile ‘com.czt.mp3recorder:library:1.0.3’

1. 语音录音封装
代码简单 自己看吧

package com.video.zlc.audioplayer;

import com.czt.mp3recorder.MP3Recorder;
import com.video.zlc.audioplayer.utils.LogUtil;

import java.io.File;
import java.io.IOException;
import java.util.UUID;
/**
 * @author zlc
 */
public class AudioManage {

    private MP3Recorder mRecorder;
    private String mDir;             // 文件夹的名称
    private String mCurrentFilePath;
    private static AudioManage mInstance;

    private boolean isPrepared; // 标识MediaRecorder准备完毕
    private AudioManage(String dir) {
        mDir = dir;
        LogUtil.e("AudioManage=",mDir);
    }

    /**
     * 回调“准备完毕”
     * @author zlc
     */
    public interface AudioStateListenter {
        void wellPrepared();    // prepared完毕
    }

    public AudioStateListenter mListenter;

    public void setOnAudioStateListenter(AudioStateListenter audioStateListenter) {
        mListenter = audioStateListenter;
    }

    /**
     * 使用单例实现 AudioManage
     * @param dir
     * @return
     */
    public static AudioManage getInstance(String dir) {
        if (mInstance == null) {
            synchronized (AudioManage.class) {   // 同步
                if (mInstance == null) {
                    mInstance = new AudioManage(dir);
                }
            }
        }
        return mInstance;
    }

    /**
     * 准备录音
     */
    public void prepareAudio() {

        try {
            isPrepared = false;
            File dir = new File(mDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String fileName = GenerateFileName(); // 文件名字
            File file = new File(dir, fileName);  // 路径+文件名字
            //MediaRecorder可以实现录音和录像。需要严格遵守API说明中的函数调用先后顺序.
            mRecorder = new MP3Recorder(file);
            mCurrentFilePath = file.getAbsolutePath();
//          mMediaRecorder = new MediaRecorder();
//          mCurrentFilePath = file.getAbsolutePath();
//          mMediaRecorder.setOutputFile(file.getAbsolutePath());    // 设置输出文件
//          mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);    // 设置MediaRecorder的音频源为麦克风
//          mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);    // 设置音频的格式
//          mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    // 设置音频的编码为AMR_NB
//          mMediaRecorder.prepare();
//          mMediaRecorder.start();
            mRecorder.start();   //开始录音
            isPrepared = true; // 准备结束
            if (mListenter != null) {
                mListenter.wellPrepared();
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e("prepareAudio",e.getMessage());
        }

    }

    /**
     * 随机生成文件名称
     * @return
     */
    private String GenerateFileName() {
        // TODO Auto-generated method stub
        return UUID.randomUUID().toString() + ".mp3"; // 音频文件格式
    }


    /**
     * 获得音量等级——通过mMediaRecorder获得振幅,然后换算成声音Level
     * maxLevel最大为7;
     * @return
     */
    public int getVoiceLevel(int maxLevel) {
        if (isPrepared) {
            try {
                mRecorder.getMaxVolume();
                return maxLevel * mRecorder.getMaxVolume() / 32768 + 1;
            } catch (Exception e) {
                 e.printStackTrace();
            }
        }
        return 1;
    }

    /**
     * 释放资源
     */
    public void release() {
        if(mRecorder != null) {
            mRecorder.stop();
            mRecorder = null;
        }
    }

    /**
     * 停止录音
     */
    public void stop(){
        if(mRecorder!=null && mRecorder.isRecording()){
            mRecorder.stop();
        }
    }

    /**
     * 取消(释放资源+删除文件)
     */
    public void delete() {
        release();
        if (mCurrentFilePath != null) {
            File file = new File(mCurrentFilePath);
            file.delete();    //删除录音文件
            mCurrentFilePath = null;
        }
    }

    public String getCurrentFilePath() {
        return mCurrentFilePath;
    }

    public int getMaxVolume(){
        return mRecorder.getMaxVolume();
    }

    public int getVolume(){
        return mRecorder.getVolume();
    }
}

2. 语音播放器封装

package com.video.zlc.audioplayer.utils;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;

/**
 *
 * @author zlc
 *
 */
public class MediaManager {

    private static MediaPlayer mMediaPlayer;   //播放录音文件
    private static boolean isPause = false;

    static {
        if(mMediaPlayer==null){
            mMediaPlayer=new MediaPlayer();
            mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {

                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    mMediaPlayer.reset();
                    return false;
                }
            });
        }
    }


    /**
     * 播放音频
     * @param filePath
     * @param onCompletionListenter
     */
    public static void playSound(Context context,String filePath, MediaPlayer.OnCompletionListener onCompletionListenter){

        if(mMediaPlayer==null){
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {
                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    mMediaPlayer.reset();
                    return false;
                }
            });
        }else{
            mMediaPlayer.reset();
        }
        try {
            //详见“MediaPlayer”调用过程图
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setOnCompletionListener(onCompletionListenter);
            mMediaPlayer.setDataSource(filePath);
            mMediaPlayer.prepare();
            mMediaPlayer.start();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            LogUtil.e("语音error==",e.getMessage());
        }
    }


    /**
     *  暂停
     */
    public synchronized static void pause(){
        if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
            mMediaPlayer.pause();
            isPause=true;
        }
    }

    //停止
    public synchronized static void stop(){
        if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
            mMediaPlayer.stop();
            isPause=false;
        }
    }

    /**
     * resume继续
     */
    public synchronized static void resume(){
        if(mMediaPlayer!=null && isPause){
            mMediaPlayer.start();
            isPause=false;
        }
    }

    public static boolean isPause(){
        return isPause;
    }

    public static void setPause(boolean isPause) {
        MediaManager.isPause = isPause;
    }

    /**
     * release释放资源
     */
    public static void release(){
        if(mMediaPlayer!=null){
            isPause = false;
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    public synchronized static void reset(){
        if(mMediaPlayer!=null) {
            mMediaPlayer.reset();
            isPause = false;
        }
    }

    /**
     * 判断是否在播放视频
     * @return
     */
    public synchronized static boolean isPlaying(){

        return mMediaPlayer != null && mMediaPlayer.isPlaying();
    }
}

3. 语音列表顺序播放

 private int lastPos = -1;
    //播放语音
 private void playVoice(final int position, String from) {

        LogUtil.e("playVoice position",position+"");
        if(position >= records.size()) {
            LogUtil.e("playVoice","全部播放完了");
            stopAnimation();
            MediaManager.reset();
            return;
        }

        String voicePath = records.get(position).getPath();
        LogUtil.e("playVoice",voicePath);
        if(TextUtils.isEmpty(voicePath) || !voicePath.contains(".mp3")){
            Toast.makeText(this,"语音文件不合法",Toast.LENGTH_LONG).show();
            return;
        }

        if(lastPos != position && "itemClick".equals(from)){
            stopAnimation();
            MediaManager.reset();
        }
        lastPos = position;

//获取listview某一个条目的图片控件
        int pos = position - id_list_voice.getFirstVisiblePosition();
        View view = id_list_voice.getChildAt(pos);
        id_iv_voice = (ImageView) view.findViewById(R.id.id_iv_voice);
        LogUtil.e("playVoice position",pos+"");

        if(MediaManager.isPlaying()){
            MediaManager.pause();
            stopAnimation();
        }else if(MediaManager.isPause()){
            startAnimation();
            MediaManager.resume();
        }else{
            startAnimation();
            MediaManager.playSound(this,voicePath, new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    //播放完停止动画 重置MediaManager
                    stopAnimation();
                    MediaManager.reset();

                    playVoice(position + 1, "loop");
                }
            });
        }
    }

4. 语音列表单个播放 复用问题处理
播放逻辑基本同上

  private int lastPosition = -1;
    private void playVoice(FendaListInfo.ObjsEntity obj, int position) {
        String videoPath = obj.path;
        if(TextUtils.isEmpty(videoPath) || !videoPath.contains(".mp3")){
            Toast.makeText(this,"语音文件不合法",Toast.LENGTH_LONG).show();
            return;
        }
        if(position != lastPosition){  //点击不同条目先停止动画 重置音频资源
            stopAnimation();
            MediaManager.reset();
        }
        if(mAdapter!=null)
            mAdapter.selectItem(position, lastPosition);
        lastPosition = position;

        id_iv_voice.setBackgroundResource(R.drawable.animation_voice);
        animationDrawable = (AnimationDrawable) id_iv_voice.getBackground();
        if(MediaManager.isPlaying()){
            stopAnimation();
            MediaManager.pause();
        }else if(MediaManager.isPause()){
            startAnimation();
            MediaManager.resume();
        }else{
            startAnimation();
            MediaManager.playSound(this,videoPath, new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    LogUtil.e("onCompletion","播放完成");
                    stopAnimation();
                    MediaManager.stop();
                }
            });
        }
    }

//核心方法
 //点击了某一个条目 这个条目isSelect=true 上一个条目isSelect需要改为false 防止滑动过程中 帧动画复用问题
    public void selectItem(int position, int lastPosition) {

        LogUtil.e("selectItem"," ;lastPosition="+lastPosition+" ;position="+position);
        if(lastPosition >= 0 && lastPosition < mDatas.size() && lastPosition != position){
            FendaListInfo.ObjsEntity bean = mDatas.get(lastPosition);
            bean.isSelect = false;
            mDatas.set(lastPosition, bean);
            notifyDataSetChanged();
        }

        if(position < mDatas.size() && position != lastPosition){
            FendaListInfo.ObjsEntity bean = mDatas.get(position);
            bean.isSelect = true;
            mDatas.set(position,bean);
        }
    }
/**
 * 适配器图片播放的动画处理
 */
private void setVoiceAnimation(ImageView iv_voice, FendaListInfo.ObjsEntity obj) {

        //处理动画复用问题
        AnimationDrawable animationDrawable;
        if(obj.isSelect){
            iv_voice.setBackgroundResource(R.drawable.animation_voice);
            animationDrawable = (AnimationDrawable) iv_voice.getBackground();
            if(MediaManager.isPlaying() && animationDrawable!=null){
                animationDrawable.start();
            }else{
                iv_voice.setBackgroundResource(R.drawable.voice_listen);
                animationDrawable.stop();
            }
        }else{
            iv_voice.setBackgroundResource(R.drawable.voice_listen);
        }
    }

5. 联系方式
qq:1509815887@qq.com
email : zlc921022@163.com
phone : 18684732678

6.下载地址

点击去下载

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值