热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

这篇文章主要为大家详细介绍了Android实现语音播放与录音功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了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 

5.下载地址

Android实现语音播放与录音

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 本文将详细介绍如何使用剪映应用中的镜像功能,帮助用户轻松实现视频的镜像效果。通过简单的步骤,您可以快速掌握这一实用技巧。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 如何在PHPcms网站中添加广告
    本文详细介绍了在PHPcms网站后台添加广告的方法,涵盖多种常见的广告形式,如百度广告和Google广告,并提供了相关设置的步骤。同时,文章还探讨了优化网站流量的SEO策略。 ... [详细]
  • 当iOS设备越狱后,某些插件可能会导致系统崩溃(白苹果)。此时,可以通过进入安全模式来排查并删除有问题的插件。本文将详细介绍如何通过特定按键组合进入不加载MobileSubstrate的安全模式,并提供相关背景知识。 ... [详细]
author-avatar
个阖家团圆
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有