千家信息网

Android怎样实现仿微信录音功能

发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,这篇文章主要介绍了Android怎样实现仿微信录音功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。实现方法:1.在xml文件中添加
千家信息网最后更新 2025年11月07日Android怎样实现仿微信录音功能

这篇文章主要介绍了Android怎样实现仿微信录音功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

实现方法:

1.在xml文件中添加

 

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

感谢你能够认真阅读完这篇文章,希望小编分享的"Android怎样实现仿微信录音功能"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!

文件 时间 篇文章 路径 功能 平方和 数据 方法 权限 语音 长度 代号 代码 价值 使用方法 兴趣 内容 变量 同时 后台 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器管理系统如何操作 网络安全工程师使用电脑推荐 咸阳软件开发价格走势 infuse 服务器订阅 html5 数据库查询 外购软件能否按软件开发销售 大学实训平台及软件开发 如何评价金砖网络安全比赛 网络安全与防护选题的背景 网络安全与信息化工作论文 镜像见证服务器已断开连接 服务器送二级备案域名 六安服务器回收价格优质商家 四川电力应急软件开发服务应用 河北大学网络安全事件应急预案 数据库字段里的换行符 下一代网络技术应用与研究 网络安全检查有哪些 数据库怎么插入一万条记录 网络安全考研分方向么 图书馆系统架构图数据库 5e2v2约战服务器分配失败 access宇哥数据库案例 软件开发和反编译是一起的吗 网络安全组实现 服务器代理商收入 网络技术开发费怎么做账 绍兴app软件开发项目 数据库分文件存储 sql数据库实训总结
0