现在的位置: 首页 > 移动开发 > 正文

Android中仿微信录音,录音后的raw文件转mp3文件

2019年11月18日 移动开发 ⁄ 共 10288字 ⁄ 字号 评论关闭

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

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

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

  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">

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

抱歉!评论已关闭.