Android中仿微信錄音,錄音後的raw文件轉mp3文件

現在很多時候需要用到錄音,然後如果我們的App是ios和android兩端的話,就要考慮錄音的文件在兩端都能使用,這個時候就需要適配,兩端的錄音文件都要是mp3文件,這樣才能保證兩邊都能播放。

針對這個,封裝了一個簡單可用的錄音控件。

   

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

<ant.muxi.com.audiodemo.view.SoundTextView
        android:id="@+id/record_audio"
        android:text="按住開始錄音"
        android:gravity="center"
        android:background="@drawable/bg_round_black"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:layout_marginBottom="40px"
        android:padding="20px"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </ant.muxi.com.audiodemo.view.SoundTextView>

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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章