Android录音实现

1 Android录音需要声明录音权限

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

2.录音文件要写到文件夹中,创建文件夹,在Application的onCreate方法中创建文件夹

@Override
public void onCreate() {
    super.onCreate();
    CrashHandler mCrashHandler = CrashHandler.getInstance();
    mCrashHandler.init(getApplicationContext(), getClass());
    initFile();
}

private void initFile() {
    //录音文件
    File audioFile = new File(Constant.UrlAudio);
    if (!audioFile.exists()) {
        audioFile.mkdirs();
    } else if (!audioFile.isDirectory()) {
        audioFile.delete();
        audioFile.mkdirs();
    }
    //拍摄图片文件
    File imageFile = new File(Constant.UrlImage);
    if (!imageFile.exists()) {
        imageFile.mkdirs();
    } else if (!imageFile.isDirectory()) {
        imageFile.delete();
        imageFile.mkdirs();
    }
}

Constant.UrlImage是个静态的文件路径

//录音文件
public static String UrlAudio = FileUtil.getSdcardPathOnSys()+"/EhmFile/media/audio/";

 3.在activity中开始录音

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.media.MediaRecorder;

import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;

public class Record2Activity extends AppCompatActivity {
    // 录音界面相关
    Button btnStart;
    Button btnStop;
    TextView textTime;
    // 录音功能相关
    MediaRecorder mMediaRecorder; // MediaRecorder 实例
    boolean isRecording; // 录音状态
    String fileName; // 录音文件的名称
    String filePath; // 录音文件存储路径
    Thread timeThread; // 记录录音时长的线程
    int timeCount; // 录音时长 计数
    final int TIME_COUNT = 0x101;
    // 录音文件存放目录
    final String audioSaveDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/audiodemo/";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record2);
        btnStart = (Button) findViewById(R.id.btn_start);
        btnStop = (Button) findViewById(R.id.btn_stop);
        textTime = (TextView) findViewById(R.id.text_time);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
// 开始录音
                btnStart.setEnabled(false);
                btnStop.setEnabled(true);
                startRecord();
                isRecording = true;
// 初始化录音时长记录
                timeThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        countTime();
                    }
                });
                timeThread.start();
            }
        });
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
// 停止录音
                btnStart.setEnabled(true);
                btnStop.setEnabled(false);
                stopRecord();
                isRecording = false;
            }
        });
    }

    // 记录录音时长
    private void countTime() {
        while (isRecording) {
            Log.d("mediaRe","正在录音");
            timeCount++;
            Message msg = Message.obtain();
            msg.what = TIME_COUNT;
            msg.obj = timeCount;
            myHandler.sendMessage(msg);
            try {
                timeThread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Log.d("mediaRec", "结束录音");
        timeCount = 0;
        Message msg = Message.obtain();
        msg.what = TIME_COUNT;
        msg.obj = timeCount;
        myHandler.sendMessage(msg);
    }

    /**
     * 开始录音 使用amr格式
     * 录音文件
     *
     * @return
     */
    public void startRecord() {
// 开始录音
        /* ①Initial:实例化MediaRecorder对象 */
        if (mMediaRecorder == null)
            mMediaRecorder = new MediaRecorder();
        try {
            /* ②setAudioSource/setVedioSource */
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置麦克风
            /*
             * ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式
             * ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)
             */
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            /* ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 */
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            fileName = DateFormat.format("yyyyMMdd_HHmmss", Calendar.getInstance(Locale.CHINA)) + ".m4a";
            //注意文件夹要创建之后才能使用
            filePath = Constant.UrlAudio + fileName;
            /* ③准备 */
            mMediaRecorder.setOutputFile(filePath);
            mMediaRecorder.prepare();
            /* ④开始 */
            mMediaRecorder.start();
        } catch (IllegalStateException e) {
            Log.i("mediaEr", "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            Log.i("mediaEr", "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
        }
    }

    /**
     * 停止录音
     */
    public void stopRecord() {
//有一些网友反应在5.0以上在调用stop的时候会报错,翻阅了一下谷歌文档发现上面确实写的有可能会报错的情况,捕获异常清理一下就行了,感谢大家反馈!
        try {
            mMediaRecorder.stop();
            mMediaRecorder.release();
            mMediaRecorder = null;
            filePath = "";
        } catch (RuntimeException e) {
            Log.e("mediaR", e.toString());
            mMediaRecorder.reset();
            mMediaRecorder.release();
            mMediaRecorder = null;
            File file = new File(filePath);
            if (file.exists())
                file.delete();
            filePath = "";
        }
    }

    // 格式化 录音时长为 秒
    public static String FormatMiss(int miss) {
        return "" + miss;
    }

    Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case TIME_COUNT:
                    int count = (int) msg.obj;
                    Log.d("meidaRe","count == " + count);
                    textTime.setText(FormatMiss(count));
                    break;
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        myHandler.removeCallbacksAndMessages(null);
    }
}

布局文件很简单

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Record2Activity">

    <Button
        android:id="@+id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="结束"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/btn_start"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开始"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/btn_stop"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="11dp"
        android:layout_marginTop="47dp"
        android:text="时间"
        app:layout_constraintStart_toStartOf="@+id/btn_start"
        app:layout_constraintTop_toBottomOf="@+id/btn_start" />
</androidx.constraintlayout.widget.ConstraintLayout>

这样就可以使用录音功能了

 


版权声明:本文为weixin_55522643原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。