现在很多时候需要用到录音,然后如果我们的App是ios和android两端的话,就要考虑录音的文件在两端都能使用,这个时候就需要适配,两端的录音文件都要是mp3文件,这样才能保证两边都能播放。

针对这个,封装了一个简单可用的录音控件。

   

使用方法:1.在xml文件中添加

    

2.别忘了申请录音权限

AndPermission.with(MainActivity.this)                .permission(Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE)                .onGranted(permissions -> {                    showSelect();                })                .onDenied(permissions -> {                    Toast.makeText(MainActivity.this,"请同意录音权限",Toast.LENGTH_SHORT).show();                })                .start();
private void showSelect() {        SoundTextView recordAudio = findViewById(R.id.record_audio);        recordAudio.setOnRecordFinishedListener(new SoundTextView.OnRecordFinishedListener() {            @Override            public void newMessage(String path, int duration) {                int index = path.lastIndexOf("/");                String fileName = path.substring(index + 1);                Log.e("录音文件", "path=: "+path );            }        });    }

使用方法如上非常简单:

主要的类

package ant.muxi.com.audiodemo.view;import android.app.Activity;import android.app.Dialog;import android.content.Context;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.TextView;import android.widget.Toast;import androidx.appcompat.widget.AppCompatTextView;import java.io.File;import ant.muxi.com.audiodemo.R;import ant.muxi.com.audiodemo.audio.ProgressTextUtils;import ant.muxi.com.audiodemo.audio.RecordManager;public class SoundTextView extends AppCompatTextView {    private Context mContext;    private Dialog recordIndicator;    private TextView mVoiceTime;    private File file;    private String type = "1";//默认开始录音 type=2,录音完毕    RecordManager recordManager;    File fileto;    int level;    private long downT;    String sountime;    public SoundTextView(Context context) {        super(context);        init();    }    public SoundTextView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        this.mContext = context;        init();    }    public SoundTextView(Context context, AttributeSet attrs) {        super(context, attrs);        this.mContext = context;        init();    }    private void init() {        recordIndicator = new Dialog(getContext(), R.style.jmui_record_voice_dialog);        recordIndicator.setContentView(R.layout.jmui_dialog_record_voice);        mVoiceTime = (TextView) recordIndicator.findViewById(R.id.voice_time);        file = new File(Environment.getExternalStorageDirectory() + "/recoder.amr");        fileto = new File(Environment.getExternalStorageDirectory() + "/recoder.mp3");        recordManager = new RecordManager(                (Activity) mContext,                String.valueOf(file),                String.valueOf(fileto));        recordManager.setOnAudioStatusUpdateListener(new RecordManager.OnAudioStatusUpdateListener() {            @Override            public void onUpdate(double db) {                //得到分贝                if (null != recordIndicator) {                    level = (int) db;                    handler.sendEmptyMessage(0x111);                }            }        });    }    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case 0x111:                    sountime = ProgressTextUtils.getSecsProgress(System.currentTimeMillis() - downT);                    long time = System.currentTimeMillis() - downT;                    mVoiceTime.setText(ProgressTextUtils.getProgressText(time));                    //判断时间                    judetime(Integer.parseInt(sountime));                    break;            }        }    };    public void judetime(int time) {        if (time > 14) {            //结束录制            Toast.makeText(mContext, "录音不能超过十五秒", Toast.LENGTH_SHORT).show();            recordManager.stop_mp3();            new Thread() {                @Override                public void run() {                    super.run();                    recordManager.saveData();                    finishRecord(fileto.getPath(), sountime);                }            }.start();            recordIndicator.dismiss();            type = "2";        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        int action = event.getAction();        switch (action) {            case MotionEvent.ACTION_DOWN:                if (type.equals("1")) {                    //开始发送时间                    downT = System.currentTimeMillis();                    recordManager.start_mp3();                    recordIndicator.show();                } else {                    Log.e("-log-", "您已经录制完毕: ");                }                                return true;            case MotionEvent.ACTION_UP:                if (type.equals("1")) {                    try {                        if (Integer.parseInt(sountime) > 2) {                            recordManager.stop_mp3();                            new Thread() {                                @Override                                public void run() {                                    super.run();                                    recordManager.saveData();                                    finishRecord(fileto.getPath(), sountime);                                }                            }.start();                            if (recordIndicator.isShowing()) {                                recordIndicator.dismiss();                            }                            type = "2";                        } else {                            recordManager.stop_mp3();                            if (recordIndicator.isShowing()) {                                recordIndicator.dismiss();                            }                            sountime = null;                            Toast.makeText(mContext, "录音时间少于3秒,请重新录制", Toast.LENGTH_SHORT).show();                        }                    } catch (Exception e) {                        recordManager.stop_mp3();                        if (recordIndicator.isShowing()) {                            recordIndicator.dismiss();                        }                        sountime = null;                        Toast.makeText(mContext, "录音时间少于3秒,请重新录制", Toast.LENGTH_SHORT).show();                    }                }                break;            case MotionEvent.ACTION_CANCEL:                if (recordIndicator.isShowing()) {                    recordIndicator.dismiss();                }                break;        }        return super.onTouchEvent(event);    }    //录音完毕加载 ListView item    private void finishRecord(String path, String time) {        if (onRecordFinishedListener != null) {            onRecordFinishedListener.newMessage(path, Integer.parseInt(time));            type = "1";        }        //发送语音        // Toasts.toast(getContext(),"您已经录完了一条语音"+myRecAudioFile);    }    private OnRecordFinishedListener onRecordFinishedListener;    public void setOnRecordFinishedListener(OnRecordFinishedListener onRecordFinishedListener) {        this.onRecordFinishedListener = onRecordFinishedListener;    }    public interface OnRecordFinishedListener {        void newMessage(String path, int duration);    }}

主要的录音管理类

public class RecordManager {    //录制成MP3格式..............................................    /**构造时候需要的Activity,主要用于获取文件夹的路径*/    private Activity activity;    /**文件代号*/    public static final int RAW = 0X00000001;    public static final int MP3 = 0X00000002;    /**文件路径*/    private String rawPath = null;    private String mp3Path = null;    /**采样频率*/    private static final int SAMPLE_RATE = 11025;    /**录音需要的一些变量*/    private short[] mBuffer;    private AudioRecord mRecorder;    /**录音状态*/    private boolean isRecording = false;    /**是否转换ok*/    private boolean convertOk = false;    public RecordManager(Activity activity, String rawPath, String mp3Path) {        this.activity = activity;        this.rawPath = rawPath;        this.mp3Path = mp3Path;    }    /**开始录音*/    public boolean start_mp3() {        // 如果正在录音,则返回        if (isRecording) {            return isRecording;        }        // 初始化        if (mRecorder == null) {            initRecorder();        }        getFilePath();        mRecorder.startRecording();        startBufferedWrite(new File(rawPath));        isRecording = true;        return isRecording;    }    /**停止录音,并且转换文件,这很可能是个耗时操作,建议在后台中做*/    public boolean stop_mp3() {        if (!isRecording) {            return isRecording;        }        // 停止        mRecorder.stop();        isRecording = false;//TODO        // 开始转换(转换代码就这两句)//        FLameUtils lameUtils = new FLameUtils(1, SAMPLE_RATE, 96);//        convertOk = lameUtils.raw2mp3(rawPath, mp3Path);//        return isRecording ^ convertOk;// convertOk==true,return true        return isRecording;    }    public void saveData(){        FLameUtils lameUtils = new FLameUtils(1, SAMPLE_RATE, 96);        convertOk = lameUtils.raw2mp3(rawPath, mp3Path);    }    /**获取文件的路径*/    public String getFilePath(int fileAlias) {        if (fileAlias == RAW) {            return rawPath;        } else if (fileAlias == MP3) {            return mp3Path;        } else            return null;    }    /**清理文件*/    public void cleanFile(int cleanFlag) {        File f = null;        try {            switch (cleanFlag) {                case MP3:                    f = new File(mp3Path);                    if (f.exists())                        f.delete();                    break;                case RAW:                    f = new File(rawPath);                    if (f.exists())                        f.delete();                    break;                case RAW | MP3:                    f = new File(rawPath);                    if (f.exists())                        f.delete();                    f = new File(mp3Path);                    if (f.exists())                        f.delete();                    break;            }            f = null;        } catch (Exception e) {            e.printStackTrace();        }    }    /**关闭,可以先调用cleanFile来清理文件*/    public void close() {        if (mRecorder != null)            mRecorder.release();        activity = null;    }    /**初始化*/    private void initRecorder() {        int bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);        mBuffer = new short[bufferSize];        mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE,                AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,                bufferSize);    }    /**设置路径,第一个为raw文件,第二个为mp3文件*/    private void getFilePath() {        try {            String folder = "audio_recorder_2_mp3";            String fileName = String.valueOf(System.currentTimeMillis());            if (rawPath == null) {                File raw = new File(activity.getDir(folder,                        activity.MODE_PRIVATE), fileName + ".raw");                raw.createNewFile();                rawPath = raw.getAbsolutePath();                raw = null;            }            if (mp3Path == null) {                File mp3 = new File(activity.getDir(folder,                        activity.MODE_PRIVATE), fileName + ".mp3");                mp3.createNewFile();                mp3Path = mp3.getAbsolutePath();                mp3 = null;            }            Log.d("rawPath", rawPath);            Log.d("mp3Path", mp3Path);        } catch (Exception e) {            e.printStackTrace();        }    }    /**执行cmd命令,并等待结果*/    private boolean runCommand(String command) {        boolean ret = false;        Process process = null;        try {            process = Runtime.getRuntime().exec(command);            process.waitFor();            ret = true;        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                process.destroy();            } catch (Exception e) {                e.printStackTrace();            }        }        return ret;    }    /**写入到raw文件*/    private void startBufferedWrite(final File file) {        Object mLock = new Object();        new Thread(new Runnable() {            @Override            public void run() {                DataOutputStream output = null;                try {                    output = new DataOutputStream(new BufferedOutputStream(                            new FileOutputStream(file)));                    while (isRecording) {//开始录制                        int readSize = mRecorder.read(mBuffer, 0,                                mBuffer.length);//是实际读取的数据长度                        for (int i = 0; i < readSize; i++) {                            output.writeShort(mBuffer[i]);                        }                        long v = 0;                        // 将 buffer 内容取出,进行平方和运算                        for (int i = 0; i < mBuffer.length; i++) {                            v += mBuffer[i] * mBuffer[i];                        }                        // 平方和除以数据总长度,得到音量大小。                        double mean = v / (double) readSize;                        double volume = 10 * Math.log10(mean);                        synchronized (mLock) {                            try {                                if(null != audioStatusUpdateListener) {                                    audioStatusUpdateListener.onUpdate(volume);                                }                                mLock.wait(100);                            } catch (InterruptedException e) {                                e.printStackTrace();                            }                        }                    }                } catch (IOException e) {                    e.printStackTrace();                } finally {                    if (output != null) {                        try {                            output.flush();                        } catch (IOException e) {                            e.printStackTrace();                        } finally {                            try {                                output.close();                            } catch (IOException e) {                                e.printStackTrace();                            }                        }                    }                }            }        }).start();    }       public RecordManager.OnAudioStatusUpdateListener audioStatusUpdateListener;     public void setOnAudioStatusUpdateListener(RecordManager.OnAudioStatusUpdateListener audioStatusUpdateListener) {        this.audioStatusUpdateListener = audioStatusUpdateListener;    }    public interface OnAudioStatusUpdateListener {        public void onUpdate(double db);    }}

完整代码:https://download.csdn.net/download/shihuiyun/11980411 

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. ELF文件查看利器之objdump用法
  6. Android番外篇——XML layout与CSS 转载
  7. 【BUG修补匠】 Android微信支付返回码-1之坑(首次调用成功第二次
  8. Power Supply 文件节点和电池服务属性对照
  9. Android(安卓)添加底层核心服务

随机推荐

  1. 介绍 Java 中的内存泄漏
  2. 诊断 Java.lang.OutOfMemoryError(OOM)
  3. 不想用 Swagger?可以试试这个神器!
  4. 测试领域,小白问题大集合(适合未入门和入
  5. Scala 与 Java 的交互操作
  6. Swagger(丝袜哥)3.0 官方 Starter 终于出了
  7. 到底要不要考研?
  8. Java 线程面试题 Top 50
  9. 推荐一款神仙颜值的 ZooKeeper 客户端工
  10. Hibernate 和 UUID 标示符