Android仿微信录音功能(录音后的raw文件转mp3文件)
程序员文章站
2023-10-31 08:34:10
现在很多时候需要用到录音,然后如果我们的app是ios和android两端的话,就要考虑录音的文件在两端都能使用,这个时候就需要适配,两端的录音文件都要是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文件,希望对大家有所帮助