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);

}

}

完整代码:http://xiazai.jb51.net/201911/yuanma/AudioDemo_jb51.rar

总结

以上所述是小编给大家介绍的Android仿微信录音功能(录音后的raw文件转mp3文件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

以上是 Android仿微信录音功能(录音后的raw文件转mp3文件) 的全部内容, 来源链接: utcz.com/p/242194.html

回到顶部