Android实现语音播放与录音功能

作者:尽人事看天意 时间:2022-01-21 15:39:09 

本文实例为大家分享了Android实现语音播放与录音的具体代码,供大家参考,具体内容如下

项目用到的技术点和亮点

  • 语音录音 (单个和列表)

  • 语音播放(单个和列表)

  • 语音录音封装

  • 语音播放器封装

  • 语音列表顺序播放

  • 语音列表单个播放 复用问题处理

因为安装原生录音不能录mp3格式文件 而mp3格式是安卓和ios公用的,所以我们需要的是能直接录取mp3文件或者录完的格式转成mp3格式

下面添加这个库 能直接录mp3文件,我觉得是最方便的

compile ‘com.czt.mp3recorder:library:1.0.3'

1. 语音录音封装

代码简单 自己看吧


package com.video.zlc.audioplayer;

import com.czt.mp3recorder.MP3Recorder;
import com.video.zlc.audioplayer.utils.LogUtil;

import java.io.File;
import java.io.IOException;
import java.util.UUID;
/**
* @author zlc
*/
public class AudioManage {

private MP3Recorder mRecorder;
private String mDir;    // 文件夹的名称
private String mCurrentFilePath;
private static AudioManage mInstance;

private boolean isPrepared; // 标识MediaRecorder准备完毕
private AudioManage(String dir) {
 mDir = dir;
 LogUtil.e("AudioManage=",mDir);
}

/**
 * 回调“准备完毕”
 * @author zlc
 */
public interface AudioStateListenter {
 void wellPrepared(); // prepared完毕
}

public AudioStateListenter mListenter;

public void setOnAudioStateListenter(AudioStateListenter audioStateListenter) {
 mListenter = audioStateListenter;
}

/**
 * 使用单例实现 AudioManage
 * @param dir
 * @return
 */
public static AudioManage getInstance(String dir) {
 if (mInstance == null) {
  synchronized (AudioManage.class) { // 同步
   if (mInstance == null) {
    mInstance = new AudioManage(dir);
   }
  }
 }
 return mInstance;
}

/**
 * 准备录音
 */
public void prepareAudio() {

try {
  isPrepared = false;
  File dir = new File(mDir);
  if (!dir.exists()) {
   dir.mkdirs();
  }
  String fileName = GenerateFileName(); // 文件名字
  File file = new File(dir, fileName); // 路径+文件名字
  //MediaRecorder可以实现录音和录像。需要严格遵守API说明中的函数调用先后顺序.
  mRecorder = new MP3Recorder(file);
  mCurrentFilePath = file.getAbsolutePath();
//   mMediaRecorder = new MediaRecorder();
//   mCurrentFilePath = file.getAbsolutePath();
//   mMediaRecorder.setOutputFile(file.getAbsolutePath()); // 设置输出文件
//   mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置MediaRecorder的音频源为麦克风
//   mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); // 设置音频的格式
//   mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置音频的编码为AMR_NB
//   mMediaRecorder.prepare();
//   mMediaRecorder.start();
  mRecorder.start(); //开始录音
  isPrepared = true; // 准备结束
  if (mListenter != null) {
   mListenter.wellPrepared();
  }
 } catch (Exception e) {
  e.printStackTrace();
  LogUtil.e("prepareAudio",e.getMessage());
 }

}

/**
 * 随机生成文件名称
 * @return
 */
private String GenerateFileName() {
 // TODO Auto-generated method stub
 return UUID.randomUUID().toString() + ".mp3"; // 音频文件格式
}

/**
 * 获得音量等级——通过mMediaRecorder获得振幅,然后换算成声音Level
 * maxLevel最大为7;
 * @return
 */
public int getVoiceLevel(int maxLevel) {
 if (isPrepared) {
  try {
   mRecorder.getMaxVolume();
   return maxLevel * mRecorder.getMaxVolume() / 32768 + 1;
  } catch (Exception e) {
    e.printStackTrace();
  }
 }
 return 1;
}

/**
 * 释放资源
 */
public void release() {
 if(mRecorder != null) {
  mRecorder.stop();
  mRecorder = null;
 }
}

/**
 * 停止录音
 */
public void stop(){
 if(mRecorder!=null && mRecorder.isRecording()){
  mRecorder.stop();
 }
}

/**
 * 取消(释放资源+删除文件)
 */
public void delete() {
 release();
 if (mCurrentFilePath != null) {
  File file = new File(mCurrentFilePath);
  file.delete(); //删除录音文件
  mCurrentFilePath = null;
 }
}

public String getCurrentFilePath() {
 return mCurrentFilePath;
}

public int getMaxVolume(){
 return mRecorder.getMaxVolume();
}

public int getVolume(){
 return mRecorder.getVolume();
}
}

2. 语音播放器封装


package com.video.zlc.audioplayer.utils;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;

/**
*
* @author zlc
*
*/
public class MediaManager {

private static MediaPlayer mMediaPlayer; //播放录音文件
private static boolean isPause = false;

static {
 if(mMediaPlayer==null){
  mMediaPlayer=new MediaPlayer();
  mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {

@Override
   public boolean onError(MediaPlayer mp, int what, int extra) {
    mMediaPlayer.reset();
    return false;
   }
  });
 }
}

/**
 * 播放音频
 * @param filePath
 * @param onCompletionListenter
 */
public static void playSound(Context context,String filePath, MediaPlayer.OnCompletionListener onCompletionListenter){

if(mMediaPlayer==null){
  mMediaPlayer = new MediaPlayer();
  mMediaPlayer.setOnErrorListener( new MediaPlayer.OnErrorListener() {
   @Override
   public boolean onError(MediaPlayer mp, int what, int extra) {
    mMediaPlayer.reset();
    return false;
   }
  });
 }else{
  mMediaPlayer.reset();
 }
 try {
  //详见“MediaPlayer”调用过程图
  mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  mMediaPlayer.setOnCompletionListener(onCompletionListenter);
  mMediaPlayer.setDataSource(filePath);
  mMediaPlayer.prepare();
  mMediaPlayer.start();
 } catch (Exception e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  LogUtil.e("语音error==",e.getMessage());
 }
}

/**
 * 暂停
 */
public synchronized static void pause(){
 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
  mMediaPlayer.pause();
  isPause=true;
 }
}

//停止
public synchronized static void stop(){
 if(mMediaPlayer!=null && mMediaPlayer.isPlaying()){
  mMediaPlayer.stop();
  isPause=false;
 }
}

/**
 * resume继续
 */
public synchronized static void resume(){
 if(mMediaPlayer!=null && isPause){
  mMediaPlayer.start();
  isPause=false;
 }
}

public static boolean isPause(){
 return isPause;
}

public static void setPause(boolean isPause) {
 MediaManager.isPause = isPause;
}

/**
 * release释放资源
 */
public static void release(){
 if(mMediaPlayer!=null){
  isPause = false;
  mMediaPlayer.stop();
  mMediaPlayer.release();
  mMediaPlayer = null;
 }
}

public synchronized static void reset(){
 if(mMediaPlayer!=null) {
  mMediaPlayer.reset();
  isPause = false;
 }
}

/**
 * 判断是否在播放视频
 * @return
 */
public synchronized static boolean isPlaying(){

return mMediaPlayer != null && mMediaPlayer.isPlaying();
}
}

3. 语音列表顺序播放


private int lastPos = -1;
//播放语音
private void playVoice(final int position, String from) {

LogUtil.e("playVoice position",position+"");
 if(position >= records.size()) {
  LogUtil.e("playVoice","全部播放完了");
  stopAnimation();
  MediaManager.reset();
  return;
 }

String voicePath = records.get(position).getPath();
 LogUtil.e("playVoice",voicePath);
 if(TextUtils.isEmpty(voicePath) || !voicePath.contains(".mp3")){
  Toast.makeText(this,"语音文件不合法",Toast.LENGTH_LONG).show();
  return;
 }

if(lastPos != position && "itemClick".equals(from)){
  stopAnimation();
  MediaManager.reset();
 }
 lastPos = position;

//获取listview某一个条目的图片控件
 int pos = position - id_list_voice.getFirstVisiblePosition();
 View view = id_list_voice.getChildAt(pos);
 id_iv_voice = (ImageView) view.findViewById(R.id.id_iv_voice);
 LogUtil.e("playVoice position",pos+"");

if(MediaManager.isPlaying()){
  MediaManager.pause();
  stopAnimation();
 }else if(MediaManager.isPause()){
  startAnimation();
  MediaManager.resume();
 }else{
  startAnimation();
  MediaManager.playSound(this,voicePath, new MediaPlayer.OnCompletionListener() {
   @Override
   public void onCompletion(MediaPlayer mediaPlayer) {
    //播放完停止动画 重置MediaManager
    stopAnimation();
    MediaManager.reset();

playVoice(position + 1, "loop");
   }
  });
 }
}

4. 语音列表单个播放 复用问题处理

播放逻辑基本同上


private int lastPosition = -1;
private void playVoice(FendaListInfo.ObjsEntity obj, int position) {
 String videoPath = obj.path;
 if(TextUtils.isEmpty(videoPath) || !videoPath.contains(".mp3")){
  Toast.makeText(this,"语音文件不合法",Toast.LENGTH_LONG).show();
  return;
 }
 if(position != lastPosition){ //点击不同条目先停止动画 重置音频资源
  stopAnimation();
  MediaManager.reset();
 }
 if(mAdapter!=null)
  mAdapter.selectItem(position, lastPosition);
 lastPosition = position;

id_iv_voice.setBackgroundResource(R.drawable.animation_voice);
 animationDrawable = (AnimationDrawable) id_iv_voice.getBackground();
 if(MediaManager.isPlaying()){
  stopAnimation();
  MediaManager.pause();
 }else if(MediaManager.isPause()){
  startAnimation();
  MediaManager.resume();
 }else{
  startAnimation();
  MediaManager.playSound(this,videoPath, new MediaPlayer.OnCompletionListener() {
   @Override
   public void onCompletion(MediaPlayer mp) {
    LogUtil.e("onCompletion","播放完成");
    stopAnimation();
    MediaManager.stop();
   }
  });
 }
}

//核心方法
//点击了某一个条目 这个条目isSelect=true 上一个条目isSelect需要改为false 防止滑动过程中 帧动画复用问题
public void selectItem(int position, int lastPosition) {

LogUtil.e("selectItem"," ;lastPosition="+lastPosition+" ;position="+position);
 if(lastPosition >= 0 && lastPosition < mDatas.size() && lastPosition != position){
  FendaListInfo.ObjsEntity bean = mDatas.get(lastPosition);
  bean.isSelect = false;
  mDatas.set(lastPosition, bean);
  notifyDataSetChanged();
 }

if(position < mDatas.size() && position != lastPosition){
  FendaListInfo.ObjsEntity bean = mDatas.get(position);
  bean.isSelect = true;
  mDatas.set(position,bean);
 }
}
/**
* 适配器图片播放的动画处理
*/
private void setVoiceAnimation(ImageView iv_voice, FendaListInfo.ObjsEntity obj) {

//处理动画复用问题
 AnimationDrawable animationDrawable;
 if(obj.isSelect){
  iv_voice.setBackgroundResource(R.drawable.animation_voice);
  animationDrawable = (AnimationDrawable) iv_voice.getBackground();
  if(MediaManager.isPlaying() && animationDrawable!=null){
   animationDrawable.start();
  }else{
   iv_voice.setBackgroundResource(R.drawable.voice_listen);
   animationDrawable.stop();
  }
 }else{
  iv_voice.setBackgroundResource(R.drawable.voice_listen);
 }
}

5.下载地址

Android实现语音播放与录音

来源:https://blog.csdn.net/rjgcszlc/article/details/78036010

标签:Android,语音,录音
0
投稿

猜你喜欢

  • Java8 CompletableFuture 异步多线程的实现

    2023-07-21 08:07:15
  • java组件commons-fileupload实现文件上传、下载、在线打开

    2022-02-24 22:16:59
  • java 完全二叉树的构建与四种遍历方法示例

    2022-03-21 00:48:04
  • JAVA实现LRU算法的参考示例

    2022-01-26 21:56:49
  • WebSocket实现Web聊天室功能

    2023-11-27 06:10:52
  • java Disruptor构建高性能内存队列使用详解

    2022-02-03 00:41:14
  • 详解context root修改无效web修改项目路径(eclipse)

    2022-08-04 13:08:46
  • android studio实现简单的计算器小功能

    2022-07-22 17:53:26
  • java 解决Eclipse挂掉问题的方法

    2023-02-19 14:05:55
  • 使用genymotion访问本地上Tomcat上数据的方法

    2022-11-23 05:51:43
  • 解决Swagger2返回map复杂结构不能解析的问题

    2022-07-15 09:17:04
  • 详解Spring Cloud负载均衡重要组件Ribbon中重要类的用法

    2023-07-06 02:54:01
  • Spring Boot 静态资源处理方式

    2022-09-14 11:14:39
  • java实现ftp文件上传下载功能

    2023-04-13 19:31:30
  • Java设计模式之java命令模式详解

    2023-11-13 16:00:36
  • C#实现简易计算器功能(1)(窗体应用)

    2022-09-30 16:59:16
  • Java 中的Printstream介绍_动力节点Java学院整理

    2021-12-21 06:08:36
  • SpringBoot2整合Ehcache组件实现轻量级缓存管理

    2022-06-18 18:11:16
  • C#异步编程Task的创建方式

    2023-07-23 06:22:43
  • springboot+gradle 构建多模块项目的步骤

    2023-02-19 00:33:31
  • asp之家 软件编程 m.aspxhome.com