欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android仿微信录音功能(录音后的raw文件转mp3文件)

程序员文章站 2023-10-31 08:34:10
现在很多时候需要用到录音,然后如果我们的app是ios和android两端的话,就要考虑录音的文件在两端都能使用,这个时候就需要适配,两端的录音文件都要是mp3文件,这样才能保证两边都...

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

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

Android仿微信录音功能(录音后的raw文件转mp3文件)Android仿微信录音功能(录音后的raw文件转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文件,希望对大家有所帮助