项目用到的技术点和亮点

  1. 语音录音 (单个和列表)
  2. 语音播放(单个和列表)
  3. 语音录音封装
  4. 语音播放器封装
  5. 语音列表顺序播放
  6. 语音列表单个播放 复用问题处理

因为安装原生录音不能录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 stubreturn 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() {@Overridepublic 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() {@Overridepublic 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 blocke.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() {@Overridepublic void onCompletion(MediaPlayer mediaPlayer) {//播放完停止动画 重置MediaManagerstopAnimation();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() {@Overridepublic 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. 联系方式
qq:1509815887@qq.com
email : zlc921022@163.com
phone : 18684732678

6.下载地址

点击去下载

语音播放与录音 (五分钟学会用 非常全面)相关推荐

  1. 五分钟学会企业的OpenStack(T版)——简介及安装方式

    五分钟学会企业的OpenStack(T版)--简介及安装方式 前言 一.OpenStack简介 二.OpenStack安装方式(T版)系列 前言 花了几天写完了OpenStack(T版)的系列文章,希 ...

  2. 五分钟学会用Simulink模型生成HDL代码

    五分钟学会用Simulink模型生成HDL代码 1 核心步骤 2 视频展示 3 生成HDL代码的注意事项 3.1 HDL支持的库和模块 3.2 设置simulink模型为可生成 hdl 的模式 3.3 ...

  3. 老滚5初始化python失败_五分钟学会怎么用python做一个简单的贪吃蛇

    Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.我们今天将利用它来制作一款大家基本都玩过的小游戏--贪吃蛇. 一.需要导入的包 import pygame ...

  4. 五分钟学会HTML5!(一)

    摘要: 毫无疑问,对于开发人员而言,HTML5已是一个热点话题.如果你需要快速了解HTML5的功能的基本原理,阅读本文是你最好的选择.本文来自The Code Project的付费搜索位置,由Solu ...

  5. 五分钟学会Playwright录制脚本的方法以及语法难点

     这篇文章系统地介绍了上手Playwright的方法,但是录制脚本部分讲解不够详尽,今天我在这里重点的介绍一下Playwright 录制脚本的方法来丰满我的Playwright系列技术文章. Play ...

  6. 五分钟学会python_关于五分钟学Python系列视频

    Up主记得我们父母辈考大学的时候,外语,尤其是英语,是一个非常火爆的专业.那个时候会英语的人相对比较少,因此能掌握流利的英文听说读写的学生可以算是稀缺人才.现在虽然英语专业人才仍然有很大市场,但是整体 ...

  7. 五分钟学会python函数_五分钟带你搞懂python 迭代器与生成器

    前言 大家周末好,今天给大家带来的是Python当中生成器和迭代器的使用. 我当初第一次学到迭代器和生成器的时候,并没有太在意,只是觉得这是一种新的获取数据的方法.对于获取数据的方法而言,我们会一种就 ...

  8. 五分钟学会使用 go modules(含在家办公使用技巧)

    作者 | 孙健波(天元)  阿里巴巴技术专家 导读:go modules 是 golang 1.11 新加的特性.如今 1.13 都已经发布了第 7 个小版本了,几乎所有大项目均已开始使用,这自然也包 ...

  9. linux系统无损迁移,五分钟学会新技巧:轻松无损迁移操作系统到SSD

    随着固态硬盘的普及,玩家手中很多没有标配SSD的电脑都需要添加一块SSD,但原本积累了大量使用习惯的操作系统和C盘数据却找不到办法很好的迁移.在新硬盘中重新做系统又比较麻烦,需要很长一段时间才能找回原 ...

  10. 智源社区AI周刊No.102:Stable Diffusion背后公司再融1亿美元;体外人脑细胞五分钟学会打乒乓,登Neuron...

    汇聚每周AI观点.研究和各类资源,不错过真知灼见和重要资讯!欢迎扫码,关注并订阅智源社区AI周刊. 编辑精选 1. Stable Diffusion背后公司再融1亿美金:独辟蹊径,开源和社区驱动的AI ...

最新文章

  1. 【Linux】使用xshell登陆时密码框为灰色,无法输入密码
  2. redis linux 文件位置,Linux下Redis的安装和部署
  3. Java泛型总结--转
  4. 动态创建ActiveRecord条件的查询 MyQuery
  5. 高等数学上-赵立军-北京大学出版社-题解-练习2.7
  6. 为什么选择springcloud微服务架构
  7. 程序设计模式浅析(plain framework商业版设计模式)
  8. pandas库基础笔记
  9. python常用字符串_Python中最常用的字符串方法!
  10. JavaScript 动态生成表格 案例
  11. 图片文字转换成word软件在线版
  12. 字符串的常用方法和常用类
  13. 在Ubuntu12.04部署OpenStack (1)
  14. RFX2401C 2.4GHz功放PA前端模块
  15. ViewBag的简单使用
  16. 蒙特卡洛算法求矩形内切圆面积
  17. DBO与DB_OWER
  18. 免费天气查询工具类源码,开箱即用,根据中国气象局API编写。高效稳定
  19. Android View部分消失效果实现
  20. 2022年系统集成项目管理工程师考试知识点:项目成本管理

热门文章

  1. 工作中常用的27个Excel函数公式
  2. xp 安装程序在计算机中识别出下列大容量存储设备,大容量存储控制器驱动程序安装步骤[图形]...
  3. 视频“云、边、端”全流程支持H.265,意味着更低的流量成本与更高的视频质量,计算压力都在边缘侧
  4. linux 编译chromium,简易编译Chromium OS内核教程
  5. linux版本即时通讯软件,Linux下即时通讯软件IM应用
  6. 友达37寸长条液晶屏P370IVN04.1-原厂长条屏
  7. Linux 嗅探 网络扫描 攻击防御神器 NMAP
  8. Android信鸽推送全解
  9. android xutils3 注解,xUtils3使用简介
  10. 华为关闭telnet命令_运营商定制的华为光猫Telnet命令恢复华为界面